Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🔐 Qué tipo de hash usa WordPress

🔐 Qué tipo de hash usa WordPress

La contraseña de su panel de administración es lo último que se interpone entre un hacker y el control total de su sitio. Una contraseña débil o un mecanismo de almacenamiento obsoleto convierten un hosting costoso y un firewall de pago en meros adornos.

A lo largo de veinte años, WordPress ha evolucionado desde MD5 hasta bcrypt de grado industrial. A partir de la versión 6.8, el hash de contraseñas se volvió moderno desde el primer momento, sin plugins ni soluciones alternativas. Pero cada propietario de un sitio debería entender exactamente qué sucede con su contraseña después de hacer clic en «Iniciar sesión».

A continuación, la cadena completa: desde que se introduce una contraseña en el formulario de acceso hasta la cadena hash en la base de datos. Con código, filtros y configuraciones específicas para quienes desean más de lo que ofrece el núcleo.

💡 Resumen rápido:

  • WordPress 6.8 y versiones posteriores aplican hash a las contraseñas mediante el algoritmo bcrypt, el mismo estándar que usan bancos y sistemas gubernamentales
  • Los hashes antiguos (MD5, phpass) se actualizan automáticamente a bcrypt en el siguiente inicio de sesión del usuario; la migración es transparente y no requiere ninguna acción manual
  • El filtro wp_hash_password_algorithm le permite cambiar a Argon2 con una sola línea de código, sin necesidad de plugins
  • El plugin PHP Native Password Hash sigue siendo una opción viable para versiones anteriores a la 6.8 y ofrece una configuración detallada de los parámetros de Argon2 a través de wp-config.php

Qué es el hash y por qué WordPress lo necesita

El hash es una transformación criptográfica unidireccional. A partir de una cadena de cualquier longitud, se obtiene una «huella digital» de tamaño fijo. Revertir un hash a la contraseña original es matemáticamente imposible; solo se pueden probar diferentes entradas y comparar los hashes resultantes.

Diagrama de hashing de contraseñas en WordPress

A diferencia del cifrado, donde los datos pueden recuperarse con una clave, un hash es un billete de ida. Cuando usted introduce una contraseña durante el inicio de sesión, WordPress la pasa por la misma función hash y compara el resultado con lo almacenado en la base de datos. Si coinciden, se concede el acceso. Si no, se deniega.

WordPress almacena los hashes en la tabla wp_users, en el campo user_pass. Si la base de datos se filtra (y esto ha ocurrido incluso a gigantes: LinkedIn, Yahoo y Tumblr perdieron cientos de millones de registros), un atacante no obtiene contraseñas legibles, sino largas cadenas bcrypt. Recuperar la contraseña a partir de una cadena así es imposible. Pero adivinarla mediante un ataque de diccionario sí es posible si el algoritmo es débil o está obsoleto. Esa es exactamente la razón por la que la evolución del hash en WordPress es tan importante.

Cómo aplicaba WordPress el hash a las contraseñas antes: MD5 y phpass

Antes de la versión 2.5 (2008), WordPress usaba MD5 simple. El algoritmo transforma cualquier contraseña en un hash de 128 bits compuesto por 32 caracteres hexadecimales. Parece seguro, pero MD5 es vulnerable a las tablas arcoíris (bases de datos precalculadas de hashes para miles de millones de contraseñas comunes). Un hacker con acceso a la base de datos simplemente busca el hash en dicha tabla y recupera al instante la contraseña original.

A partir de la versión 2.5, WordPress cambió a phpass, una biblioteca portátil basada en bcrypt (Blowfish). Añadía una «sal» aleatoria a la contraseña y ejecutaba el resultado a través de la función hash múltiples veces (por defecto, 2^8 = 256 iteraciones). La sal inutilizaba las tablas arcoíris: dos contraseñas idénticas para diferentes usuarios producían hashes distintos. Al mismo tiempo, phpass mantenía la compatibilidad con versiones anteriores de MD5; las contraseñas antiguas no dejaban de funcionar y se actualizaban sin problemas al nuevo formato al iniciar sesión.

Esto fue suficiente durante muchos años. Pero la industria avanzó: el hardware moderno (granjas de GPU y ASIC) puede probar miles de millones de hashes por segundo. El algoritmo bcrypt con un factor de coste configurable se convirtió en el estándar de la industria. Y a partir de WordPress 6.8, el núcleo lo utiliza de forma nativa.

WordPress 6.8 y bcrypt: qué cambió

La versión «Cecil» de WordPress 6.8 (abril de 2025) trajo una transición completa a bcrypt. Anteriormente, el núcleo utilizaba su propia clase PasswordHash de la biblioteca phpass; ahora llama a la función nativa de PHP password_hash() con la constante PASSWORD_BCRYPT.

Seguridad de WordPress mediante hashing nativo de PHP

Cambios clave en la función wp_hash_password():

  • bcrypt por defecto. Todas las contraseñas nuevas se procesan mediante password_hash() usando el algoritmo bcrypt y el factor de coste establecido por el servidor PHP (normalmente 10).
  • Migración automática de contraseñas antiguas. Cuando un usuario inicia sesión, WordPress verifica mediante password_needs_rehash() si el hash necesita actualizarse. El antiguo formato phpass ($P$...) se reemplaza de forma transparente por bcrypt.
  • Protección para contraseñas largas. bcrypt trunca las contraseñas de más de 72 bytes, lo que reduce la entropía. WordPress 6.8 lo soluciona aplicando un pre-hash con SHA-384 usando la clave de dominio wp-sha384 y codificando en base64. Una contraseña de 100 caracteres conserva toda su fortaleza.
  • Filtros para una configuración flexible. Aparecieron nuevos hooks: wp_hash_password_algorithm (selección de algoritmo) y wp_hash_password_options (parámetros: cost, memory_cost, threads).

La llamada a wp_hash_password() en el núcleo de WordPress 6.8 tiene este aspecto:

1function wp_hash_password( $password ) {
2 global $wp_hasher;
3
4 if ( ! empty( $wp_hasher ) ) {
5 return $wp_hasher->HashPassword( trim( $password ) );
6 }
7
8 if ( strlen( $password ) > 4096 ) {
9 return '*';
10 }
11
12 $algorithm = apply_filters( 'wp_hash_password_algorithm', PASSWORD_BCRYPT );
13 $options = apply_filters( 'wp_hash_password_options', array(), $algorithm );
14
15 if ( PASSWORD_BCRYPT !== $algorithm ) {
16 return password_hash( $password, $algorithm, $options );
17 }
18
19 $password_to_hash = base64_encode(
20 hash_hmac( 'sha384', trim( $password ), 'wp-sha384', true )
21 );
22
23 return '$wp' . password_hash( $password_to_hash, $algorithm, $options );
24}

La función primero comprueba si la lógica de hash ha sido sobrescrita por un plugin externo (la variable global $wp_hasher). Luego rechaza las contraseñas de más de 4096 caracteres; dichos intentos de inicio de sesión devuelven *, lo que imposibilita la autenticación. A continuación viene la parte interesante: el filtro wp_hash_password_algorithm determina el algoritmo. Si la selección NO es bcrypt, la contraseña se procesa directamente. Si se selecciona bcrypt, la contraseña pasa primero por SHA-384 con la clave wp-sha384, se codifica en base64 y solo entonces se pasa a password_hash(). El resultado es un hash con el prefijo $wp, que distingue el bcrypt «de WordPress» del bcrypt estándar. Esto es útil para auditorías de base de datos o integración con sistemas externos.

Cómo reforzar el hash con Argon2

bcrypt es una base excelente. El siguiente paso es Argon2, el ganador de la Competición de Hash de Contraseñas de 2015. Argon2 se diseñó específicamente para resistir ataques con GPU: consume mucha memoria, y las tarjetas de vídeo son el cuello de botella en este caso.

Ejemplo de código para migrar WordPress a Argon2

Opción 1: el hook wp_hash_password_algorithm (WordPress 6.8+)

Añada esto al archivo functions.php de su tema hijo o mediante el plugin Code Snippets:

1add_filter( 'wp_hash_password_algorithm', function() {
2 return PASSWORD_ARGON2ID;
3});

En un par de segundos, WordPress cambia a Argon2ID. Las contraseñas antiguas se re-procesan automáticamente cuando los usuarios inician sesión. Su hosting debe ser compatible con Argon2 en PHP; necesita la versión 7.3 o superior para Argon2ID. Puede verificar la disponibilidad llamando a password_algos().

Para un ajuste detallado de los parámetros, utilice el hook complementario:

1add_filter( 'wp_hash_password_options', function( $options, $algorithm ) {
2 if ( PASSWORD_ARGON2ID === $algorithm ) {
3 return array(
4 'memory_cost' => 65536, // 64 MB
5 'time_cost' => 4,
6 'threads' => 2,
7 );
8 }
9 return $options;
10}, 10, 2 );

El parámetro memory_cost determina cuánta memoria debe usar el algoritmo al calcular el hash; cuanto mayor sea el valor, más difícil se vuelve el ataque de fuerza bruta basado en GPU. time_cost establece el número de iteraciones, y threads establece el número de hilos.

Opción 2: el plugin PHP Native Password Hash

Para versiones de WordPress anteriores a la 6.8, el plugin PHP Native Password Hash hace lo mismo. Reemplaza toda la lógica de hashing con password_hash() nativo, admite bcrypt y Argon2, y no tiene interfaz; todos los ajustes se configuran mediante constantes en wp-config.php:

1define( 'WP_PASSWORD_HASH_ALGO', PASSWORD_ARGON2ID );
2define( 'WP_PASSWORD_HASH_OPTIONS', [
3 'memory_cost' => 65536,
4 'time_cost' => 4,
5 'threads' => 2,
6] );

El plugin no se ha actualizado en más de dos años, pero su código es mínimo y estable. Con WordPress 6.8, su funcionalidad está integrada en el núcleo, así que puede desinstalarlo y usar los filtros nativos en su lugar.

Generadores de hash: qué funciona hoy

Hay situaciones en las que necesita generar un hash manualmente: escribir una contraseña directamente en la base de datos mediante phpMyAdmin o migrar usuarios desde un sistema externo.

Generador de hash de contraseña de WordPress vía WP-CLI

El generador en línea de passwordtool.hu, popular en la época de las versiones antiguas de WordPress, ya no está disponible: el sitio cambió de dueño. Alternativas funcionales hoy:

  • WP-CLI: el comando wp user update <id> --user_pass="newpassword" hace todo correctamente mediante wp_hash_password(). Rápido, seguro y con garantía de ser correcto.
  • Un script PHP en la raíz del sitio: cree temporalmente un archivo con una llamada a echo wp_hash_password('password'); y elimínelo inmediatamente después de usarlo.
  • Cualquier generador bcrypt en línea: por ejemplo, bcrypt.online. Pero recuerde: WordPress 6.8 añade el prefijo $wp y un pre-hash SHA-384, así que un hash bcrypt estándar no funcionará para inserción directa en la base de datos.

En la práctica, WP-CLI es la opción más fiable.

Cómo elegir una contraseña que no sea descifrable

Ni siquiera bcrypt le salvará si la contraseña es admin123. Los atacantes empiezan su ataque con fuerza bruta por diccionario.

Interfaz de verificación de fortaleza de contraseña en WordPress

La herramienta zxcvbn de Dropbox, incorporada en WordPress para evaluar contraseñas en el panel de administración, rechaza patrones comunes: fechas de nacimiento, 123456 y qwerty, nombres de mascotas. Analiza las contraseñas contra diccionarios, distribuciones de teclado y patrones de sustitución de caracteres. Una calificación de «débil» significa que la contraseña puede adivinarse en segundos.

Tres reglas prácticas:

  • Palabras aleatorias, no sopa de caracteres. Una contraseña compuesta de cuatro o cinco palabras en inglés sin relación entre sí y con separadores (por ejemplo, correct-horse-battery-staple) es más fácil de recordar que Tr0ub4dor&3 y tarda mucho más en descifrarse.
  • La longitud importa más que la complejidad. Dieciséis letras minúsculas aleatorias proporcionan mayor entropía que 8 caracteres con símbolos especiales. Y bcrypt en WordPress 6.8 preserva la entropía de contraseñas de cualquier longitud razonable mediante el pre-hash SHA-384.
  • Use un gestor de contraseñas. La memoria humana es una mala herramienta para gestionar una docena de contraseñas únicas. 1Password es el estándar de oro de pago con plan familiar, KeePass es gratuito y de código abierto con base de datos local, Bitwarden es el punto medio ideal: gratuito, basado en la nube y de código abierto.
Gestor de contraseñas para almacenar credenciales de WordPress

Un gestor de contraseñas genera, almacena y autocompleta contraseñas. Usted solo necesita recordar una contraseña maestra. Y si el sitio admite autenticación de dos factores, actívela sin falta. Una contraseña más un código de un solo uso desde una aplicación hacen que el inicio de sesión sea prácticamente invulnerable.

Vídeo: cómo funciona el hash de contraseñas en WordPress

Una explicación breve del mecanismo de hash, desde que se introduce una contraseña hasta su almacenamiento en la base de datos de WordPress:

⁉️🤔 Preguntas frecuentes

¿Las contraseñas con hash MD5 antiguo siguen funcionando en WordPress 6.8+?

Sí. Cuando un usuario inicia sesión, WordPress detecta el formato de hash antiguo, verifica la contraseña usando el algoritmo previo y, si todo cuadra, actualiza el hash a bcrypt de forma transparente. No hace falta eliminar usuarios antiguos ni forzar restablecimientos de contraseña.

¿Es necesario el plugin PHP Native Password Hash en WordPress 6.8 y versiones posteriores?

No. Todo lo que hacía el plugin (hash mediante password_hash() y soporte para Argon2) ahora está disponible a través de los filtros nativos wp_hash_password_algorithm y wp_hash_password_options. El plugin solo sigue siendo relevante para versiones inferiores a 6.8.

¿Puedo volver de Argon2 a bcrypt?

Técnicamente sí, cambiando el algoritmo en el filtro. Pero los hashes Argon2 antiguos no se reconocerán y los usuarios tendrán que restablecer sus contraseñas. Si está experimentando con algoritmos en un sitio en producción, haga primero una copia de seguridad completa de la base de datos.

¿Ayuda bcrypt si la base de datos se filtra?

bcrypt hace que descifrar contraseñas por fuerza bruta a partir de hashes filtrados sea cientos de miles de veces más lento que con MD5. Con un factor de coste de 10, un hash en una CPU moderna tarda aproximadamente 0,1 segundos en calcularse; mil millones de intentos llevarían años. Pero si la contraseña es password, se encontrará en la primera iteración de un ataque de diccionario. El algoritmo protege las contraseñas complejas; nada puede salvar las débiles.

¿Cómo verifico que mis contraseñas se están almacenando con bcrypt?

Revise la tabla wp_users mediante phpMyAdmin. El campo user_pass para usuarios nuevos (y aquellos que iniciaron sesión tras actualizar a 6.8) debe comenzar con el prefijo $wp (el marcador del nuevo formato bcrypt de WordPress). Los hashes phpass antiguos tienen el aspecto $P$B.... Para una comprobación masiva, ejecute esta consulta SQL: SELECT COUNT(*) FROM wp_users WHERE user_pass NOT LIKE '$wp$%' AND user_pass NOT LIKE '$P$%';. Le mostrará cuántas contraseñas están atascadas en un formato obsoleto, si las hay.

Qué hacer ahora mismo con el hash de WordPress

Si su sitio WordPress está en la versión 6.8 o posterior, ya está protegido por bcrypt; no necesita hacer nada. El núcleo actualiza automáticamente los hashes antiguos cuando los usuarios inician sesión y la migración es completamente transparente.

Si desea usar Argon2, añada el filtro wp_hash_password_algorithm con PASSWORD_ARGON2ID en functions.php. Primero, verifique que su hosting lo soporta: ejecute var_dump(password_algos()); mediante un script de prueba. La mayoría de los proveedores de hosting modernos lo tienen.

Para versiones anteriores a la 6.8, instale el plugin PHP Native Password Hash; le proporcionará bcrypt o Argon2 sin modificar el núcleo. Y programe una actualización de WordPress de paso: cada actualización mayor cierra decenas de vulnerabilidades, no solo en el hashing.

Y lo más importante, cambie admin123 por algo decente. Ningún algoritmo puede salvarlo de un ataque de diccionario si su contraseña figura entre las primeras cien entradas de la lista rockyou.txt.