Instalar y configurar el directorio OpenLDAP
Existe una interesante variedad de directorios LDAP disponibles en GNU/Linux, siendo algunos de los más importantes OpenLDAP, 389 Directory Server, OpenDS y Apache Directory. Si bien todos presentan características similares, elegí utilizar OpenLDAP por ser el más antiguo, existe mucha información al respecto, es muy flexible, y está disponible en los repositorios de las distribuciones más importantes.
A continuación describiré cómo instalar y configurar OpenLDAP. Si bien mi trabajo fue realizado en debian, no debería variar demasiado en otras distribuciones.


Instalación

En debian y derivados, instalar OpenLDAP es tan simple como ejecutar:
# apt-get install slapd ldap-utils
donde slapd es el demonio que provee la funcionalidad ldap, y ldap-utils contiene un set de herramientas para administrar y testear el server.

Durante el proceso de instalación, el configurador del paquete (debconf) requerirá los siguientes datos básicos:
  • Nombre DNS de nuestro dominio (ej: demasiadovivo.org).
  • Nombre de la organización a utilizar en el DN base. En general utilizarán el mismo que el nombre DNS (ej: demasiadovivo.org).
  • Contraseña del administrador.
  • Base de datos de fondo para almacenar los datos LDAP. Si bien openLDAP acepta distintas bases de datos, es recomendable utilizar la de Berkeley (BDB) que no es una BD relacional, sino una que permite almacenar varios items por cada clave y logra mejor performance en casos de muchas lecturas y pocas escrituras. Todo esto encaja perfecto con LDAP, porque son justamente estos los atributos de un directorio.
  • Remover la base de datos cuando el paquete slapd se purgue? es buena idea setear que no, así no borramos accidentalmente la base de datos LDAP.
  • Permitir el protocolo LDAPv2? esto dependerá de los clientes que estemos utilizando. Dado que LDAPv3 ya esta muy maduro e implementado en la mayoría de los sistemas, lo mejor es decir no a esta pregunta.
En debian 6 (squeeze) el archivo de configuración del demonio OpenLDAP se encuentra en /usr/share/slapd/slapd.conf. En otras distribuciones puede encontrarse en /etc/ldap/slapd.conf, /etc/openldap/slapd.conf o /usr/local/etc/openldap/slapd.conf. En dicho archivo podrán ver que se importan archivos que contienen los esquemas básicos, así como configuración de permisos para escribir y leer registros, tipo de base de datos, ubicación de la base de datos (/var/lib/ldap en debian), el nivel de logging, y varias cosas más.

Una vez instalado el paquete, podemos probar si el servidor se instaló y configuró correctamente, utilizando ldapsearch. ldapsearch es una herramienta que nos servirá mucho para testear la configuración del servidor y, como su nombre lo indica, sirve para hacer búsquedas dentro de directorio.
Para realizar la prueba, pediremos todos los objetos que se encuentren en el servidor:
ldapsearch -b dc=demasiadovivo,dc=org -H ldap://localhost -x
donde:
  -b indica el DN base done iniciar la búsqueda
  -H es para ingresar la URI del server
  -x indica que utilice autenticación simple
Como no utilizamos ningún fitro y no indicamos qué atributos traer, ldapsearch traerá todo.


ldap.conf

Para evitar tener que ingresar los datos referentes al DN base y la URI o dirección de servidor en cada conexión con el servidor ldap, podemos almacenar esta información en el archivo /etc/ldap.conf
ldap.conf se utiliza para configuraciones default concernientes a los clientes ldap. Los dos valores más utilizados son URI y BASE, que sirven justamente para lo explicado en el párrafo anterior. Un ejemplo de este archivo es el siguiente:
URI    ldap://demasiadovivo.org ldaps://demasiadovivo.org
BASE    dc=demasiadovivo,dc=org
Con esto nos evitamos, por ejemplo, los parámetros -b y -H en ldapsearch =)


Agregar, modificar, y eliminar entradas del directorio

Los datos LDAP son intercambiados utilizando un formato de texto plano denominado LDIF (LDAP Data Interchange Format). Utilizando archivos LDIF podemos agregar, modificar, elminar y renombrar entradas del directorio.
Cada entrada (registro) continee un conjunto de atributos y están separadas por líneas en blanco. Ya vimos ejemplos de este formato cuando utilizamos ldapsearch para testear el servicio.
Para editar la información del directorio, simplemente creamos un archivo ldif y utilizamos la herramienta ldapadd o ldapmodify. Para eliminar entradas, se utiliza ldapdelete.

En secciones anteriores vimos que la estructura del árbol del directorio se puede armar en base a unidades organizativas (organizational units - OU), algo muy común en sistemas de usuarios centralizado (Active Directory, y GNU/Linux con NSS-LDAP y PAM). Las OU básicas de un sistema de usuarios centralizado son People y Group. Podemos crear estas OUs utilizando un archivo ou.ldif que contenga:
dn: ou=People,dc=demasiadovivo,dc=org
ou: People
objectClass: organizationalUnit

dn: ou=Group,dc=demasiadovivo,dc=org
ou: Group
objectClass: organizationalUnit
y luego ejecutando ldapadd de la siguiente forma:
$ ldapadd -c -x -D cn=admin,dc=dvpem,dc=org -W -f ou.ldif
donde:
-c indica que continúe procesando si encuentra errores
-x indica que utilice autenticación simple
-D setea el DN con el cual realizar el bind (usuario de autenticación)
-W pide el password
-f permite importar los datos del archivo
Como se observa, con -x -D cn=admin,dc=dvpem,dc=org -W realizamos la autenticación con el usuario admin, dado que con acceso anónimo no es posible modificar registros de la base de datos. Más adelante veremos cómo autenticar utilizando SASL en lugar de autenticación simple.

Podemos ver el resultado ejecutando la siguiente búsqueda:
$ ldapsearch -x ou=People
$ ldapsearch -x ou=Group

Modificar la configuración

La configuración del servicio LDAP se almacena en el archivo slapd.conf, pero si se desea hacer cambios en en la misma, una vez que se actualiza dicho archivo, es necesario reiniciar el demonio slapd, algo que es muy contraproducente en un sistema que está en producción atendiendo cientos o miles de consultas. Por suerte, desde la versión 2.3 de OpenLDAP, es posible editar la configuración online. A partir de dicha versión, la configuración se almacena una base de datos separada, con un esquema y DIT predefinidos (cuyo base DN es cn=config), y la cual se encuentra en el directorio slapd.d (en debian /etc/ldap/slapd.d/). Esta base de datos posee administración en tiempo de ejecución a través de operaciones LDAP con datos en formato LDIF y se puede acceder y editar a través del conjunto de herramientas slapacl, slapadd, slapauth, slapcat, slapdn y slaptest.
Para ver las entradas de configuración, se puede utilizar slapcat de la misma manera que se utiliza ldapsearch. Por ejemplo, para ver la configuración de la base de datos, se debe ejecutar:
# slapcat -b cn=config -a olcDatabase=*
donde -b indica el sufijo o DN base, y -a permite utilizar filtros.

De esta forma tenemos que la configuración del directorio se realiza a través de atributos en entradas del directorio, y la mayoría de estos comienzan con el prefijo "olc" (OpenLDAP configuration). Además, algunas de las entradas tienen nombres con números entre llaves ({}). Esto se debe a que ni las entradas, ni los atributos de un directorio tienen un orden específico, pero el orden es necesario para la configuración, porque existen dependencias. Los números en los nombres aseguran que la configuración se ejecute en el orden correspondiente, asegurando la consistencia. En general estos números se generan automáticamente a medida que se crean las entradas.


Control de acceso

En la configuración default de un OpenLDAP recién instalado existen dos permisos para acceder al directorio:
  • utilizando el usuario admin que tiene control total. Este usuario está declarado en el DN base con cn=admin (por ej: cn=admin,dc=demasiadovivo,dc=org). La contraseña de este usuario se setea durante la instalación del directorio.
  • acceso de lectura de cualquier entrada de forma anónima, es decir, sin ningún tipo de autenticación.
Este todo o nada no suele alcanzar para ninguna organización, por lo tanto es necesario conocer cómo se administran los permisos.
El acceso a las entradas del directorio se configura a través del atributo olcAccess, cuyo formato es:
olcAccess: <directiva acceso="" de="">
olcAccess: <directiva acceso="" de="">
<access directive=""> ::= to <what>
    [by <who> <access> <control>]+
<what> ::= * |
    [dn[.<basic-style>]=<regex> | dn.<scope-style>=<dn>]
    [filter=<ldapfilter>] [attrs=<attrlist>]
<basic-style> ::= regex | exact
<scope-style> ::= base | one | subtree | children
<attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
<attr> ::= <attrname> | entry | children
<who> ::= * | [anonymous | users | self
    | dn[.<basic-style>]=<regex> | dn.<scope-style>=<dn>]
    [dnattr=<attrname>]
    [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
    [peername[.<basic-style>]=<regex>]
    [sockname[.<basic-style>]=<regex>]
    [domain[.<basic-style>]=<regex>]
    [sockurl[.<basic-style>]=<regex>]
    [set=<setspec>]
    [aci=<attrname>]
<access> ::= [self]{<level>|<priv>}
<level> ::= none | auth | compare | search | read | write
<priv> ::= {=|+|-}{w|r|s|c|x|0}+
<control> ::= [stop | continue | break]
donde la parte <what> selecciona las entradas y/o atributos a los cuales se aplica el acceso, <who> especifica que entidades tienen acceso, y <access> especifica el tipo de acceso otorgado. Se soportan múltiples tripletas <who> <access> <control>, permitiendo otorgar distinto tipo de acceso a distintas entidades.
Para observar los accesos default de todas las bases de datos, basta con ejecutar:
# slapcat -b cn=config -a olcAccess=*
Por ejemplo, ejecutando slapcat con el siguiente filtro es posible observar los accesos default a la base de datos principal:
# slapcat -b cn=config -a olcDatabase={1}hdb
  ...
  olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=demasiadovivo,dc=org" write by * none
  olcAccess: {1}to dn.base="" by * read
  olcAccess: {2}to * by self write by dn="cn=admin,dc=demasiadovivo,dc=org" write by * read
  ...
Con esta información se ve que los atributos userPassword (el password del usuario) y shadowLastChange (última fecha de modificación del password) tienen:
  • acceso de escritura para el propio usuario (self) y para el administrador (dn="cn=admin,dc=demasiadovivo,dc=org")
  • tiene acceso de lectura de forma anonima en caso de que se este realizando una autenticación (anonymous auth)
  • ningún acceso para el resto de los usuarios (* none).
Un punto a tener en cuenta es que en debian squeeze (al menos en mi caso) sólo el usuario root tiene permiso para modificar la configuración, utilizando el modo de autenticación externa de LDAP. Es decir, LDAP valida el usuario del sistema operativo.
El problema es que este modo de autenticación NO viene habilitado por defecto y requiere activación de TLS/SSL en el servidor LDAP. Esta tarea no resultó tan trivial como pensaba y no pude habilitarlo.
Para poder acceder a la configuración, existe un mecanismo alternativo. En la base de datos config, existe el usuario admin, pero por default no tiene password asignado. Para habilitar el uso de este usuario con autenticación simple, primero hay que crear la contraseña con slappasswd:
# slappasswd -h {SSHA}
y luego editar el archivo /etc/ldap/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif para agregar la siguiente línea debajo del nombre de usuario:
olcRootDN: cn=admin,cn=config   //esta línea ya existe en el archivo
olcRootPW: {SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Finalmente, reiniciar el servicio:
# /etc/init.d/slapd restart
y testear que funciona:
$ ldapsearch -x -D cn=admin,cn=config -W -b cn=config
Cómo armar los permisos y otorgarlos está excelentemente explicado en la sección 5.3. Access Control del manual de OpenLDAP, por lo tanto no tiene sentido que lo repita aquí.


Clientes gráficos

Si bien podemos administrar todo el directorio a través de archivos LDIF, esto puede resultar engorroso y contraproducente en el día a día. Por suerte existen herramientas gráficas que nos ayudan a administrar el directorio de manera más simple.
Algunas de estas herramientas son:

Referencias

- OpenLDAP provider on Debian squeeze
- OpenLDAP installation on Debian
- OpenLDAP - 2. A Quick-Start Guide
- Debian 5.0 y OpenLDAP con TLS
- OpenLDAP - 5. Configuring slapd
- LDAP Administration Guide
- Zarafa LDAP cn config How To
- HowTo:LDAP Debian 6 (squeeze)
LDAP: Un directorio liviano
Un protocolo que se ha popularizado muchísimo en los últimos años es LDAP. El mismo es utilizado en la mayoría de las empresas, ya sea con Active Directory o con alguna de las múltiples soluciones para GNU/Linux como OpenLDAP, o 389 Directory Server.
Existen librerías para la mayoría de los lenguajes de programación que soportan LDAP, por lo cual existen muchos programas que lo utilizan.
Este protocolo es la base de cualquier sistema de directorio actual (Active Directory entre ellos), y es muy importante que todo administrador y/o programador conozca acerca de el.
Este artículo los introducirá en el mundo LDAP, explicando de qué trata, cómo funciona, la terminología, cómo es la autenticación y el formato de las búsquedas. El mismo forma parte del proyecto Autenticación y administración centralizada de usuarios en GNU/Linux.


Qué es?

Lightweight Directory Access Protocol (LDAP) es una base de datos especial (no relacional) que provee servicios de directorio basado en el estándar X.500, diseñada para almacenar información basada en atributos y soportar filtros sofisticados en búsquedas. A diferencia de una base de datos relacional, LDAP está optimizado para realizar búsquedas y organiza de forma distinta los datos.
Piensen en un directorio como una guía telefónica. En la guía encontramos personas con sus atributos (nompre, apellido, dirección y teléfono) organizadas en base a la letra de su apellido.
Un directorio informático que estamos acostumbrados a utilizar es la lista de direcciones de email. En la lista de emails encontramos las direcciones de email de nustros contactos, así como el nombre, teléfono, dirección física, etc. Podemos filtrar esta lista para buscar compañeros de trabajo, de universidad, por nombre, etc.
El "Light" en el nombre de LDAP se debe a que es una implementación más liviana que el anterior estandar X.500 denominado Directory Access Protocol, el cual estaba diseñado para trabajar sobre el stack OSI.

El modelo de información en LDAP está basado en entradas. Una entrada es un conjunto de atributos que tiene un nombre único (Distinguished Name - DN). El DN es utilizado para distinguir la entrada unequívocamente y se arma a partir de su RDN (Relative Distinguished Name), construido a partir de algún/os atributo/s de la entrada, y el DN de la entrada padre. Cada atributo de la entrada tiene un tipo y uno o varios valores. Los tipos suelen representarse con un string nemotécnico como 'cn' (common name), 'c' (country), 'ou' (organization unit), etc.
La información del directorio se organiza en forma de árbol y a este se lo denomina directory information tree (DIT). La jerarquía del árbol se arma a partir de información geográfica tomando como base del árbol o bien el nombre DNS. Dentro de esta jerarquía se pueden definir varias unidades organizativas, personas, dispositivos, etc.
Un ejemplo de entrada LDAP es:
dn: cn=demasiadovivo,dc=itfreekzone,dc=blogspot,dc=com
cn: demasiadovivo
givenName: demasiadovivo
mail: espameasiqueres@gmail.com
manager: cn=Javiz,dc=je-photography,dc=blogspot,dc=com
objectClass: person
En el ejemplo, el DN es "cn=demasiadovivo,dc=itfreekzone,dc=blogspot,dc=com" que está formado por el atributo common name, y los atributos domain component (dc) de las entradas padre. El resto son los atributos de la entrada. Como pueden observar, una entrada puede contener referencias a otras entradas, como es el caso del atributo manager que referencia a la entrada "cn=Javiz,dc=je-photography,dc=blogspot,dc=com".

El protocolo utiliza el port TCP 389 por defecto, en caso de no utilizar ssl, y 636 en caso de hacerlo.


Esquemas, Clases de objeto, Atributos y entradas

Como vimos, el directorio está formado por entradas, las que a su vez están formadas por un conjunto de atributos. Estos atributos se agrupan en clases de objetos (objectClass), las que a su vez se empaquetan en esquemas (schemes). Todas las objectClass y los atributos se definen dentro de esquemas. En OpenLDAP pueden encontrar la definición de los atributos y clases de objetos en el directorio /etc/ldap/schema/.

Los atributos se definen por separado y se pueden utilizar en una o varias objectClass. Para poder utilizar un atributo en una entrada, ésta debe contener alguna objectClass que contenga el atributo, y a su vez, la objectClass debe estar incluida en algún esquema reconocido por el servidor LDAP.

Las objectClass se pueden organizar jerárquicamente, en cuyo caso heredan todas las propiedades de sus padres o SUPerior. Estas objectClass pueden ser STRUCTURAL, en cuyo caso se usan para crear entradas, AUXILIARY en cuyo caso se pueden agregar en cualquier entrada, o ABSTRACT. El ejemplo más común de objectClass ABSTRACT es top, que forma el mayor nivel de cualquier jerarquía objectClass. Cada una de estas definiciones pueden tener atributos obligatorios y otros opcionales.

Las entradas agrupan conjuntos de objectClass, donde cada una debe contener obligatoriamente (y sólo puede contener una) STRUCTURAL. Además, puede contener una ABSTRACT y un número arbitrario de AUXILIARY.


Autenticación

LDAP soporta varios métodos de autenticación para acceder al directorio, existiendo dos principales que deben ser soportados (según el estándar):
  • Método de Autenticación Simple (Simple Authentication Method). Provee tres mecanismos de autenticación:
    • Autenticación anónima de enlace simple. Conexión LDAP sin usuario ni contraseña.
    • Autenticación sin autenticación de enlace simple. Se debe utilizar el nombre de usuario de un usuario válido, pero no es necesario proveer contraseña.
    • Autenticación de Usuario/Contraseña de enlace simple. En este caso se utiliza usuario y password para la autenticación, pero el password se transmite de forma plana.
  • Autenticación Simple y Capa de Seguridad (Simple Authentication and Security Layer - SASL). SASL es un framework para proveer autenticación y servicios seguros de datos a través de mecanismos reemplazables. El estándar de SASL sólo define uno de estos mecanismos (denominado EXTERNAL) pero las implementaciones más utilizadas soportan los siguientes:
    • DIGEST-MD5: provee un mecanismo para utilizar la autenticación HTTP Digest dentro del framework SASL. Este mecanismo envía un MD5 del password en lugar del password en texto plano, sobre una conexión sin encripción.
    • EXTERNAL: permite al cliente requerir que el servidor use credenciales provistas por un mecanismo externo al mecanismo de autenticación del cliente. La autenticación externa puede ser a través de la información de login del sistema operativo, IPSec, TLS o algún otro medio.
    • GSSAPI: permite al cliente utilizar tokens GSSAPI como credenciales para la autenticación. El token GSSAPI pueden ser Kerberos TGT o token NTLM.
    • GSSAPI-SPNEGO (Active Directory): es un mecanismo GSSAPI pero que contiene una negociación cliente-servidor para elegir el mecanismo de seguridad preferido según lo soportado por el cliente y el servidor.
En todos los casos, por cuestiones de seguridad, lo mejor es utilizar una capa de encripción por debajo del proceso de autenticación, como puede ser TLS (SSL) o IPSec. El método y mécanismo de autenticación más seguro es SASL usando GSSAPI con kerberos y sobre conexión encriptada. En orden de mejor a peor, las opciones son las siguientes:
  • SASL usando GSSAPI con kerberos y sobre conexión encriptada.
  • SASL usando GSSAPI con NTLMv2 y sobre conexión encriptada (sólo en Active Directory).
  • SASL usando GSSAPI con kerberos.
  • SASL usando GSSAPI con NTLMv2 (sólo en AD).
  • SASL usando GSSAPI con NTLM y sobre conexión encriptada (sólo en Active Directory).
  • Autenticación Simple, usuando usuario/contraseña sobre conexión encriptada.
  • SASL usando GSSAPI con NTLM (sólo en AD).


Búsquedas en el directorio

La sintaxis para realizar búsquedas no es muy intuitiva y muy distinta a la forma en que consultamos bases de datos relacionales a través de SQL, pero con el tiempo (como todo) uno se acostumbra.
Los parámetros son los siguientes:

  • baseObject: el DN de la entrada donde deseamos comenzar la búsqueda (ej: dc=demasiadovivo,dc=org)
  • scope: qué elementos bajo el baseObject buscar.
  • filer: criterio para seleccionar elementos dentro del scope. Los fitros se construyen utilizando operadores de igualdad y se pueden concatenar utilizando operadores booleanos en notación prefija. Pueden encontrar una buena explicación sobre construcción de filtros en Red Hat - LDAP Search Filters, Appendix A - LDAP: Text Search Filter y MS LDAP Query Basics.
  • derefAliases: cuando y cómo seguir entradas que son alias.
  • atributos: que atributos retornar en el resultado (ej: cn mail).
  • sizeLimit, timeLimit: máxima cantidad de entradas a retornar y el tiempo máximo permitido para ejecutar la búsqueda.
  • typesOnly: retornar sólo el tipo de los atributos, sin los valores.

Una excelente herramienta para realizar búsquedas en LDAP es ldapsearch, la cual viene en el paquete ldap-utils. Un ejemplo es el siguiente:
ldapsearch -b dc=itfreekzone,dc=blogspot,dc=com "(cn=demasiadovivo)" mail
donde usamos como baseObject "dc=itfreekzone,dc=blogspot,dc=com", como filtro (cn=demasiadovivo), y el atributo que deseamos traer es "mail".


Lo que viene...

Próximamente publicaré un artículo sobre cómo instalar y configurar el servicio de directorio más utilizando en entornos *nix (principalmente GNU/Linux), denominado OpenLDAP.


Referencias

- OpenLDAP - 1. Introduction to OpenLDAP Directory Services
- LDAP Wiki
- Chapter 3. LDAP Schemas, objectClasses and Attributes
- 6. LDAP Lightweight Directory Access Protocol
- LDAP for Rocket Scientists
Hardening PHP
PHP es el lenguaje más popular para la creación de Webs, y por lo tanto muy conocido, y a la vez atacado.
Si bien es trabajo del programador (y el mayor responsable de) tomar los recaudos necesarios para que sus aplicaciones no sean vulnerables, un administrador de sistemas puede utilizar varias opciones para que el servidor sea lo más resistente posible. PHP ofrece varias opciones que aumentan la seguridad significativamente, si se encuentran bien configuradas.

La siguiente es una lista de directivas que se pueden configurar en el archivo de configuración de php (/etc/php.ini, o /etc/php5/apache2/php.ini, dependiendo la distribución) para mejorar la seguridad del servidor:
  • Restringir el acceso al sistema de archivos. Dado que los sites se alojarán en /var/www, salvo casos excepcionales, los scripts PHP no necesitan acceso al resto del sistema de archivos, a excepción del directorio /tmp que es donde se alojan los archivos cuando el usuario hace un upload. Por ello, es posible restringir los directorios a los que se puede acceder, mediante la opción:
    open_basedir = /var/www:/tmp
    Esta configuración se puede cambiar por site en el correspondiente Virtual Host, utilizando la directiva:
    php_admin_value open_basedir /var/www/[nombre site]/
  • Deshabilitar funciones riesgosas. Hay funciones que deben ser permitidas sólo en casos particulares, debido a que se usan raramente y representan un gran riesgo. Esta configuración se realiza con la directiva disable_functions:
    disable_functions = show_source, system, shell_exec, passthru, exec, phpinfo, popen, proc_open
  • No revelar información de PHP en los headers. Esto le permitiría a un atacante saber que el servidor posee PHP, además de la versión instalada, y así poder realizar un ataque más específico:
    expose_php = Off
  • No exponer errores de scripts al cliente. Los errores de programación no deben quedar expuestos a los clientes, sino que deben loggearse en archivos para que el programador los pueda depurar:
    display_errors = Off
    display_startup_errors = Off
  • Loggear errores permiten detectar cuál fue la falla que causó que el programa no funcione o lo haga de forma imprevisible:
    log_errors = On
  • No utilizar register_globals. Esta funcionalidad se considera extremadamente peligrosa y por default viene desactivada en toda configuración actual, pero por las dudas se debe checkear que el valor sea el siguiente:
    register_globals = 0
  • No utilizar magic_quotes. PHP provee, hasta la versión 5, de una utilidad para escapar caracteres peligrosos (', “, \, NULL), antes de ser utilizados por los scripts del servidor. Esto permite evitar algunos ataques de SQL Injection, pero tiene complicaciones con las distintas codificaciones de caracteres y además puede introducir problemas en la programación. Este tipo de controles deben estar implementados en la aplicación y no en el servidor, por lo cual a partir de PHP 5.3 se considera deprecated y en la versión 6 ya no existe.
    magic_quotes_gpc = Off
    magic_quotes_runtime = Off
    magic_quotes_sybase = Off
  • Para realizar upload de archivos desde el cliente, utilizar el directorio tmp correspondiente al site, es decir /var/www/[nombre site]/tmp. Esta configuración se realiza en el virtual host con la sentencia:
    php_admin_value upload_tmp_dir /var/www/[nombre site]/tmp
  • No tratar las URLs (como http:// o ftp://) como archivos. En caso de encontrar un error en la programación, un atacante podría realizar remote file inclusion si esto se encuentra activado.
    allow_url_fopen = Off
    allow_url_include = Off
  • Cambiar el nombre de la variable de sesión. Por defecto esta variable se llama PHPSESSID y demuestra que el servidor ejecuta PHP, y que la página actual está escrita en PHP. Si bien esto agrega poca seguridad, agrega una traba más al atacante.
    session.name = SESSION_ID
Como dije, estas opciones ayudan a la seguridad, pero no evitan, por ejemplo, que un programa vulnerable a SQLi permita a un atacante romper la base de datos.
Espero que les sean de utilidad!


Referencias

- Description of core php.ini directives
- Securing PHP: Step-by-Step
Links: ACLs en GNU/Linux
Hace años que abandoné esta sección que denominé "Links", y ahora encontré una buena razón para retomarla... mi trabajo con ACLs =)

En GNU/Linux la asignación de permisos a archivos y directorios se realizó históricamente con los permisos estándar Unix. El sistema de permisos es una de las primeras cosas que se enseñan en cualquier tutorial o manual de este sistema operativo, ya que son un concepto nuevo para casi cualquier usuario desktop Windows (donde los permisos suelen estar ocultos para el usuario...).
Los permisos Unix se administran por usuario, grupo y otros, y es posible asignar lectura, escritura y ejecución (rwx), además de algunos bits adicionales como sticky bit, set user id y set group id.
Esta forma de asociar permisos con archivos y directorios es suficiente para la gran mayoría de los casos, pero se queda corto cuando hay varios usuarios y grupos en juego, y se desea mayor granularidad.

Una forma bien conocida (al menos para cualquier estudiante de computación) de asignar permisos es utilizar listas de control de acceso (Access Control Lists - ACLs). Las ACLs permiten asignar permisos a listas de usuarios o grupos, en lugar de asignar permisos a sólo un usuario o grupo en particular, como sucede en el sistema Unix tradicional. Esta es la forma en que se asignan los permisos en la familia Windows NT.

Si bien GNU/Linux implementa POSIX ACLs desde hace años, no son tan utilizadas entre los linuxeros, y pocas veces mencionadas en los manuales introductorios. Dado que se utiliza poco, no hay muchas herramientas gráficas que lo implementen (una es eiciel), y por lo tanto la mejor manera es hacerlo por consola. Las herramientas utilizadas para setear y obtener las ACLs son setfacl y getfacl, y vienen en el paquete acl.
Para poder utilizar ACLs, el sistema de archivos debe poseer esta capacidad, y la partición debe ser montada con la opción acl. Casi todos los filesystems modernos la implementan, por lo que no deberían tener problemas con ello, sólo es cuestión de modificar el /etc/fstab para que se monte con la opción correspondiente.
Lo bueno es que si se activa el uso de POSIX ACLs, todavía es posible utilizar el sistema Unix tradicional, dado que, por compatibilidad, las mismas se crearon con esto en mente.

A continuación les dejo una interesante lista de páginas donde se explica el uso de ACLs en GNU/Linux. Anímense, que una vez que se acostumbran, son fáciles de administrar!

- POSIX Access Control Lists on Linux. Completísimo paper donde se discute el uso de ACLs en sistemas tipo Unix, describiendo el estandar POSIX ACLs, el orden en que se evalúan los permisos, ejemplos, análisis de performance, el uso en sistemas de archivos de red NFS y Samba. Es un buen punto de partida.
- Using ACLs with Fedora Core 2   (Linux Kernel 2.6.5). Muy buen artículo sobre el uso de ACLs, con varios escenarios como ejemplo para ver mejor su funcionalidad. Si bien el artículo asume el uso de Fedora, sirve para cualquier distribución.
- Linux ACL (Access Control Lists). Tutorial práctico sobre el uso de ACLs en Linux.
- Samba-3: Windows file and directory. Descripción del uso de ACLs en Samba.
- ACL(Access Control List) Configuration in Debian. Pequeño artículo sobre la configuración de ACLs en debian.

Espero que les sea de utilidad ^_^
Instalación de MIT Kerberos
En el artículo anterior aprendimos sobre qué es kerberos, y para qué sirve. Es hora de ver cómo instalar un servidor para este servicio.
Este artículo forma parte del proyecto Autenticación y administración centralizada de usuarios en GNU/Linux (Autenticación y administración centralizada de usuarios en GNU/Linux).

Si bien existen varias implementaciones del protocolo, elegí MIT kerberos por estar desarrollado por MIT, autores del protocolo original, ser muy completa, muy soportada por librerías y la más utilizada. Otras implementaciones bastante utilizadas son Heimdal y GNU Shishi.

Antes de comenzar a instalar kerberos, es muy importante que los relojes de los hosts participantes estén sincronizados. Como se explicó, kerberos es muy dependiente del tiempo, una desincronización conlleva problemas de acceso.
También es importante tener un servidor de nombres de dominio con los registros correspondientes a cada host, incluidos los registros PTR, dado que kerberos utiliza los nombres de dominio para validar el hosts desde donde se piden los tickets.

A continuación se describe la instalación de kerberos en debian y derivados, pero en otras distribuciones es muy similar. Por su parte, la configuración del sistema es igual para todas las distribuciones.
En debian y derivados, instalar el servicio kerberos (con kdc incluido) es tan simple como ejecutar:
  # apt-get install krb5-admin-server
La interfaz debconf de este paquete pregunta por parámetros básicos para el funcionamiento de kerberos:
  • configurar realm con el nombre del dominio, por ejemplo: demasiadovivo.org
  • escribir la dirección del servidor kerberos (es decir, la dirección del servidor donde estamos instalando kerberos, en este caso): kdc01.demasiadovivo.org
  • En este paso, obviamente necesitarán tener registrado el nombre kdc01 en el servidor de nombres. Lo mejor es tener un servidor de nombres propio para la red interna. Instalar y configurar bind es simple, por lo cual no debería implicar mayores problemas.
  • escribir el nombre del servidor administrativo de kerberos (cambio de contraseñas). Al igual que en el punto anterior, dado que estamos instalando el servidor kerberos, el nombre será el del mismo servidor actual: kdc01.demasiadovivo.org. El servidor administrativo es el que permite al administrador conectarse remotamente (herramienta kadmin) y trabajar sobre la base de datos de kerberos.
Al terminar la configuración inicial, tanto kadmind como kdc intentarán iniciar pero fallarán, dado que todavía no configuramos ningún realm.
Toda esta configuración inicial se puede realizar a mano, editando el archivo /etc/krb5.conf.

Para la creación de realms, poseemos la herramienta krb5_newrealm. Al ejecutar este comando, se creará la base de datos de kerberos para nuestro realm, y nos solicitará un password (master key del KDC) que se utiliza para generar la clave a almacenar en el stash (/etc/krb5kdc/stash), la cual sirve para encriptar la base de datos. Como se imaginan, este password es MUY importante y debe ser lo más fuerte posible. Aquel que posea el password, será capaz de desencriptar la base de datos y obtener todas las claves de los usuarios.

Una vez generado el realm, hace falta editar /etc/krb5.conf para agregar nuestro dominio default. Cuando abran este archivo se encontrarán que la sección [realms] cuenta con muchos realms famosos (varios del MIT, GNU.ORG, stanford.edu, etc). Si quieren tener una configuración limpia, lo mejor es eliminar todos estos realms; lo mismo para la sección [domain_realm]. Ahora, para agregar el dominio default, editen la definición del realm para que quede como lo siguiente:
[realms]
  DEMASIADOVIVO.ORG = {
    kdc = kdc01.demasiadovivo.org
    admin_server = kdc01.demasiadovivo.org
    default_domain = demasiadovivo.org
  }
y agreguen el dominio a la definición de dominios:
[domain_realm]
  .demasiadovivo.org = DEMASIADOVIVO.ORG
  demasiadovivo.org = DEMASIADOVIVO.ORG
se colocan tanto el nombre de dominio como el nombre de dominio iniciando con punto ".", para indicar que se aplica a todos los subdominios del mismo.
Por defecto, kerberos loggea en syslog, pero si quieren tener los logs separados, pueden agregar la sección [logging] con una definición como la siguiente:
[logging]
  kdc = FILE:/var/log/kerberos/kdc.log
  admin_server = FILE:/var/log/kerberos/kadmin.log
  default = FILE:/var/log/kerberos/krblib.log
Si utilizan el path propuesto anteriormente, deberán crear el correspondiente directorio en /var/log
  # mkdir /var/log/kerberos
Para que los cambios surtan efecto, reiniciar tanto kadmin como el kdc
  /etc/init.d/krb5-admin-server restart
  /etc/init.d/krb5-kdc restart
Una vez instalado y configurado el servicio, podemos testear como va todo. Para esto, usamos la herramienta kadmin.local, la cual es como kadmin, pero destinada a utilizarse localmente, y por ello el usuario debe estar logueado en el servidor con una cuenta de usuario lo suficientemente privilegiada para poder abrir la base de datos de kerberos (por ej. root). A diferencia de kadmin que requiere un usuario de kerberos válido para acceder, kadmin.local no requiere password dado que el usuario que la utiliza es un administrador del servidor.
Usemos entonces kadmin.local de la siguiente forma:
  # kadmin.local
  Authenticating as principal root/admin@DEMASIADOVIVO.ORG with password.
  kadmin.local: listprinc
  K/M@DEMASIADOVIVO.ORG
  kadmin/admin@DEMASIADOVIVO.ORG
  kadmin/changepw@DEMASIADOVIVO.ORG
  kadmin/dvpem01.demasiadovivo.org@DEMASIADOVIVO.ORG
  kadmin/history@DEMASIADOVIVO.ORG
  krbtgt/DEMASIADOVIVO.ORG@DEMASIADOVIVO.ORG
  kadmin.local: quit
Lo que hicimos es entrar al modo administración de kerberos y listar los principals existentes con listprinc.

Los permisos para administrar kerberos se configuran en /etc/krb5kdc/kadm5.acl. Como vimos, kerberos permite utilizar roles, y en este archivo podemos utilizarlos. Por defecto vemos que figura el acl "*/admin *", el cual está deshabilitado, como comentario. Este acl permite acceso de administración full a todos los usuarios cuyo principal tenga el rol admin. Si descomentamos esta línea, podemos utilizar el rol admin en los principals para indicar qué usuarios pueden administrar kerberos.
Agregando el principal root/admin, podremos acceder con el usuario root a través de kadmin:
# kadmin.local
Authenticating as principal root/admin@DEMASIADOVIVO.ORG with password.
kadmin.local: addprinc root/admin
WARNING: no policy specified for root/admin@DEMASIADOVIVO.ORG; defaulting to no policy
Enter password for principal "root/admin@DEMASIADOVIVO.ORG":
Re-enter password for principal "root/admin@DEMASIADOVIVO.ORG":
Principal "root/admin@DEMASIADOVIVO.ORG" created.
Y podemos probar utilizando el comando:
  # kadmin
  Authenticating as principal root/admin@DEMASIADOVIVO.ORG with password.
  Password for root/admin@DEMASIADOVIVO.ORG:
  kadmin:
Si vemos el prompt de kadmin, es que todo fue bien.


Referencias

- The Kerberos protocol and its implementations
- Kerberos V5 System Administrator's Guide
- Kerberos FAQ, v2.0
- MIT Kerberos installation on Debian
- Kerberos Infrastructure HOWTO