Título: Configuración segura de Apache para WordPress Publicado por: el-brujo en 12 Julio 2011, 19:51 pm A raíz del post “Listar los plugins de WordPress” en “Un informático en el lado del mal”, vamos a ver una configuración de Apache que evite revelar la presencia de los plugins y otras opciones.
La configuración del VirtualHost debería ser similar a la siguiente, recortando algunas partes irrelevantes: <VirtualHost *:80> ServerAdmin webmaster@dummy-host.example.com DocumentRoot "/var/www/blog/htdocs/" ServerName systemadmin.es DirectoryIndex index.php <Directory /var/www/blog/htdocs/> Options FollowSymLinks AllowOverride None Order deny,allow Allow from all </Directory> <Files wp-login.php> Order Deny,Allow Allow from 1.2.3.4 Deny from All </Files> <Directory /var/www/blog/htdocs/wp-admin> Options FollowSymLinks AllowOverride None Order Deny,Allow Allow from 1.2.3.4 Deny from All </Directory> <Filesmatch ^wp-config.php$> Deny from all </Filesmatch> <Directory /var/www/blog/htdocs/wp-content/plugins> DirectorySlash Off </Directory> RewriteEngine On RewriteCond %{REQUEST_URI} !/(about|wp-includes|wp-content|images|wp-admin|wp-login)/ RewriteCond %{REQUEST_URI} !/(about|google|sitemap|wp-comments-post.php|wp-login.php|favicon.ico|xmlrpc.php|buscador.xml) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </VirtualHost> Las partes importantes son: Deshabilitar mod_autoindex: Se trata de un modulo de Apache para hacer listados del contenido de los directorios. Personalmente prefiero eliminar dicho modulo de apache al instalarlo mediante la opción de configure –disable-autoindex. Podemos comprobar si esta cargado el modulo mediante httpd -M: # /usr/local/apache22/bin/httpd -M | grep index Syntax OK Deshabilitar el .htaccess: Independientemente por la perdida de rendimiento que supone el htaccess, supone un riesgo permitir que un fichero pueda modificar la configuración de apache, por esto lo deshabilitamos mediante: AllowOverride None La configuración que tengamos en el .htaccess la deberemos mover a la configuración del VirtualHost. Típicamente los rewrites, a los que deberemos añadir la siguiente regla antes de cualquier RewriteCond o RewriteRule: RewriteEngine On Restricciones por IP en wp-login.php y wp-admin: En el caso que sea un blog personal lo podemos limitar a nuestra IP o si la tenemos dinámica siempre podemos usar OpenVPN para restringir el acceso, además de cifrar las comunicaciones. En la configuración de Apache indicamos mediante el Allow que IPs permitimos: Order Deny,Allow Allow from 1.2.3.4 Deny from All Proteger archivos sensibles como por ejemplo el wp-config.php: Los ficheros con configuración del blog, por ejemplo los datos de conexión al MySQL no son nunca servidos, sino que se leen desde otro PHP. Así, podemos denegar que sean servidos. En condiciones normales, aunque sean servidos por el Apache, sería una página en blanco pero en el caso que falle el modulo de PHP (o exista un error en al configuración del Apache referente al PHP) se podría servir el contenido del fichero sin ejecutar. Esto pasó, ya hace años, a un proveedor de alojamiento gratuito muy conocido en España publicándose un montón de contraseñas. La configuración que evita que dicho fichero sea servido es: <Filesmatch ^wp-config.php$> Deny from all </Filesmatch> Evitar la detección de plugins de WordPress mediante el script http-wp-plugins para nmap. Sin añadir ninguna opción adicional no detecta los plugins ya que en el script vemos lo siguiente: local target if wp_root then -- Give user-supplied argument the priority target = wp_root .. "/wp-content/plugins/" .. line .. "/" elseif wp_autoroot then -- Maybe the script has discovered another WordPress content directory target = wp_autoroot .. "wp-content/plugins/" .. line .. "/" else -- Default WP directory is root target = "/wp-content/plugins/" .. line .. "/" end Realiza una búsqueda del nombre del plugin seguido de una barra, dando siempre 404. Pero el modulo mod_dir si que añade una diferencia que permite detectar si un directorio existe. Por defecto, si el directorio existe pero no le hemos añadido una barra final hace un redirect al directorio con la barra: # curl -I systemadmin.es/wp-content/plugins/akismet HTTP/1.1 301 Moved Permanently Date: Mon, 04 Jul 2011 19:55:28 GMT Server: Apache Location: http://systemadmin.es:81/wp-content/plugins/akismet/ Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 # curl -I systemadmin.es/wp-content/plugins/akismet/ HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:55:30 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 Por el contrario, si el directorio no existe no realiza este redirect: # curl -I systemadmin.es/wp-content/plugins/noexisto_luego_existo HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:55:34 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 # curl -I systemadmin.es/wp-content/plugins/noexisto_luego_existo/ HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:55:36 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 Lo que evita que para esta configuración sean detectados los plugins. Pero si modificamos el plugin de nmap para que no incluya la barra final si que los podremos detectar con el mismo diccionario: local target if wp_root then -- Give user-supplied argument the priority target = wp_root .. "/wp-content/plugins/" .. line elseif wp_autoroot then -- Maybe the script has discovered another WordPress content directory target = wp_autoroot .. "wp-content/plugins/" .. line else -- Default WP directory is root target = "/wp-content/plugins/" .. line end Con esta modificación podremos ver como sí que encuentra los plugins instalados dentro del directorio plugins (que no significa que esten habilitados): $ nmap -p80 --script=http-wp-plugins --script-arg 'http-wp-plugins.root="/",http-wp-plugins.search=all' systemadmin.es Starting Nmap 5.59BETA1 ( http://nmap.org ) at 2011-07-04 19:41 CEST Nmap scan report for systemadmin.es (87.98.227.154) Host is up (0.044s latency). rDNS record for 87.98.227.154: jordi.prats.systemadmin.es PORT STATE SERVICE 80/tcp open http | http-wp-plugins: | search amongst the 14170 most popular plugins (...) | akismet (...) Nmap done: 1 IP address (1 host up) scanned in 62.73 seconds Esta característica que hace detectables los plugins la podemos deshabilitar mediante la opción DirectorySlash. Por lo que podemos añadirla exclusivamente para el directorio de plugins con: <Directory /var/www/systemadmin.es/htdocs/wp-content/plugins> DirectorySlash Off </Directory> Una vez aplicados los cambios en el Apache podremos comprobar como el redirect ha desaparecido, comportándose igual con un directorio que existe: # curl -I systemadmin.es/wp-content/plugins/akismet HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:59:46 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 # curl -I systemadmin.es/wp-content/plugins/akismet/ HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:59:49 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 Que con uno que no existe: # curl -I systemadmin.es/wp-content/plugins/noexisto_luego_existo HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:59:53 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 # curl -I systemadmin.es/wp-content/plugins/noexisto_luego_existo/ HTTP/1.1 404 Not Found Date: Mon, 04 Jul 2011 19:59:54 GMT Server: Apache Vary: Accept-Encoding Content-Type: text/html; charset=iso-8859-1 Por lo que dicho script ya no detecta que plugins de WordPress están instalados: $ nmap -p80 --script=http-wp-plugins --script-arg 'http-wp-plugins.root="/",http-wp-plugins.search=all' systemadmin.es Starting Nmap 5.59BETA1 ( http://nmap.org ) at 2011-07-04 20:03 CEST Nmap scan report for systemadmin.es (87.98.227.154) Host is up (0.038s latency). rDNS record for 87.98.227.154: jordi.prats.systemadmin.es PORT STATE SERVICE 80/tcp open http |_http-wp-plugins: nothing found amongst the 14170 most popular plugins, use --script-arg http-wp-plugins.search=<number|all> for deeper analysis) Nmap done: 1 IP address (1 host up) scanned in 62.83 seconds Evidentemente, si el diccionario se modificara para buscar ficheros que deben estar presentes en el caso que el plugin este instalado (ficheros de estilo, imagenes…) esto no serviría de nada. Gracias a estas modificaciones en la configuración del VirtualHost de Apache complicaremos un poco más la identificación y explotación de vulnerabilidades, con la esperanza que se busquen un objetivo más fácil. Fuente: http://systemadmin.es/2011/07/configuracion-segura-de-apache-para-wordpress |