Eliminando el nombre de usuario de la cookie 'wordpress_logged_in'

9

Estoy trabajando con un cliente con algunas medidas de seguridad estrictas. Después de someternos a una revisión de seguridad, se nos notificó que el nombre de usuario almacenado en la cookie iniciada, p. Ej.

wordpress_logged_in[username]|[hash]

Es algo que tiene que ser eliminado. Dado que esta es una parte integral del sistema de inicio de sesión, no estoy seguro de cómo eliminarlo y mantener la sesión.

Phatskat
fuente

Respuestas:

10

Breve introducción

Después de un rápido vistazo al código fuente de WP, creo que he encontrado una solución ...

WordPress utiliza dos funciones para configurar y analizar las cookies de autenticación:

  • wp_generate_auth_cookie
  • wp_parse_auth_cookie

Hay un filtro en el wp_generate_auth_cookiellamado auth_cookieque probablemente podría utilizar para cambiar el contenido de la galleta, pero no hay en el interior del filtro wp_parse_auth_cookie, pero ...

Ambas funciones están definidas en pluggable.php, lo que significa que puede escribir sus propias implementaciones para ellas y sobrescribir las predeterminadas.

Solución

  1. Escriba su propio complemento (llamémoslo Mejor cookie de autenticación)
  2. Implemente sus propios wp_generate_auth_cookiey wp_parse_auth_cookiefunciones dentro de este complemento.
  3. Activa tu plugin.

Puede encontrar mi implementación de muestra (basada fuertemente en versiones originales) de estas funciones a continuación:

if ( !function_exists('wp_generate_auth_cookie') ) :
/**
 * Generate authentication cookie contents.
 *
 * @since 2.5.0
 *
 * @param int $user_id User ID
 * @param int $expiration Cookie expiration in seconds
 * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
 * @param string $token User's session token to use for this cookie
 * @return string Authentication cookie contents. Empty string if user does not exist.
 */
function wp_generate_auth_cookie( $user_id, $expiration, $scheme = 'auth', $token = '' ) {
    $user = get_userdata($user_id);
    if ( ! $user ) {
        return '';
    }

    if ( ! $token ) {
        $manager = WP_Session_Tokens::get_instance( $user_id );
        $token = $manager->create( $expiration );
    }

    $pass_frag = substr($user->user_pass, 8, 4);

    $key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );

    // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
    $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
    $hash = hash_hmac( $algo, $user->user_login . '|' . $expiration . '|' . $token, $key );

    $cookie = $user_id . '|' . $expiration . '|' . $token . '|' . $hash;

    /**
     * Filter the authentication cookie.
     *
     * @since 2.5.0
     *
     * @param string $cookie     Authentication cookie.
     * @param int    $user_id    User ID.
     * @param int    $expiration Authentication cookie expiration in seconds.
     * @param string $scheme     Cookie scheme used. Accepts 'auth', 'secure_auth', or 'logged_in'.
     * @param string $token      User's session token used.
     */
    return apply_filters( 'auth_cookie', $cookie, $user_id, $expiration, $scheme, $token );
}
endif;


if ( !function_exists('wp_parse_auth_cookie') ) :
/**
 * Parse a cookie into its components
 *
 * @since 2.7.0
 *
 * @param string $cookie
 * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
 * @return array Authentication cookie components
 */
function wp_parse_auth_cookie($cookie = '', $scheme = '') {
    if ( empty($cookie) ) {
        switch ($scheme){
            case 'auth':
                $cookie_name = AUTH_COOKIE;
                break;
            case 'secure_auth':
                $cookie_name = SECURE_AUTH_COOKIE;
                break;
            case "logged_in":
                $cookie_name = LOGGED_IN_COOKIE;
                break;
            default:
                if ( is_ssl() ) {
                    $cookie_name = SECURE_AUTH_COOKIE;
                    $scheme = 'secure_auth';
                } else {
                    $cookie_name = AUTH_COOKIE;
                    $scheme = 'auth';
                }
        }

        if ( empty($_COOKIE[$cookie_name]) )
            return false;
        $cookie = $_COOKIE[$cookie_name];
    }

    $cookie_elements = explode('|', $cookie);
    if ( count( $cookie_elements ) !== 4 ) {
        return false;
    }

    list( $user_id, $expiration, $token, $hmac ) = $cookie_elements;

    $user = get_userdata($user_id);
    $username = ( ! $user ) ? '' : $user->user_login;

    return compact( 'username', 'expiration', 'token', 'hmac', 'scheme' );
}
endif;

Mi versión de estas funciones reemplaza user_logincon user_id. Pero debería ser un buen comienzo para cambiarlo a algo aún más complejo (es decir, hash específico del usuario, o algo así).

Krzysiek Dróżdż
fuente
Buena respuesta. Aunque esperaré hasta el último día de mi período de recompensa. :)
Anónimo Ornitorrinco
Voy a aceptar esto, aunque no lo probaré porque ya no necesito esta solución. Claramente pones mucho esfuerzo para cavar en la raíz del sistema, agradezco el esfuerzo :)
phatskat
1
Si bien este enfoque es bueno, debe tener en cuenta que no ofrece más protección. El nombre de usuario se sustituye por la ID de usuario, pero el nombre de usuario se puede obtener de la ID de usuario mediante una solicitud a example.com?author=123, que realiza una redirección canónica a una URL como example.com/author/john.
John Blackbourn
1
@john lee atentamente por favor. He mencionado que puede hacer que sea mucho más seguro almacenar algunos hash aleatorios en cookies en lugar de ID de usuario.
Krzysiek Dróżdż