Usuwanie nazwy użytkownika z pliku cookie „wordpress_logged_in”

9

Pracuję z klientem z pewnymi ścisłymi środkami bezpieczeństwa. Po przejrzeniu kontroli bezpieczeństwa zostaliśmy powiadomieni, że nazwa użytkownika zapisana w logowanym pliku cookie, np

wordpress_logged_in[username]|[hash]

to coś, co należy usunąć. Ponieważ jest to integralna część systemu logowania, nie jestem pewien, jak go usunąć i utrzymać sesję.

phatskat
źródło

Odpowiedzi:

10

Krótkie wprowadzenie

Po szybkim przejrzeniu kodu źródłowego WP myślę, że znalazłem rozwiązanie ...

WordPress używa dwóch funkcji do ustawiania i analizowania plików cookie uwierzytelniania:

  • wp_generate_auth_cookie
  • wp_parse_auth_cookie

Istnieje wp_generate_auth_cookiewywoływany filtr, auth_cookiektórego prawdopodobnie możesz użyć do zmiany zawartości pliku cookie, ale nie ma w nim filtra wp_parse_auth_cookie, ale ...

Obie te funkcje są zdefiniowane w pluggable.php, co oznacza, że ​​możesz dla nich pisać własne implementacje i zastępować domyślne.

Rozwiązanie

  1. Napisz własną wtyczkę (nazwijmy ją Better Auth Cookie)
  2. Zaimplementuj własne wp_generate_auth_cookiei wp_parse_auth_cookiefunkcje w tej wtyczce.
  3. Aktywuj swoją wtyczkę.

Poniżej znajduje się moja przykładowa implementacja (oparta na oryginalnych wersjach) tych funkcji:

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;

Moja wersja tych funkcji zastępuje user_loginsię user_id. Ale powinien to być dobry początek do zmiany go na coś jeszcze bardziej złożonego (np. Skrótu specyficznego dla użytkownika lub czegoś takiego).

Krzysiek Dróżdż
źródło
Niezła odpowiedź. Chociaż poczekam do ostatniego dnia mojej nagrody. :)
Anonimowy Dziobak
Zaakceptuję to, chociaż nie będę tego testować, ponieważ nie potrzebuję już tego rozwiązania. Wyraźnie
włożyłeś
1
Chociaż takie podejście jest dobre, należy pamiętać, że nie zapewnia ono już żadnej ochrony. Nazwa użytkownika zastępuje identyfikator użytkownika, ale nazwę użytkownika można uzyskać z identyfikatora użytkownika poprzez żądanie do example.com?author=123, które dokonuje kanonicznego przekierowania na adres URL taki jak example.com/author/john.
John Blackbourn
1
@john przeczytaj uważnie. Wspomniałem, że możesz łatwo zwiększyć bezpieczeństwo przechowywania losowego skrótu w pliku cookie zamiast ID użytkownika.
Krzysiek Dróżdż