Menghapus nama pengguna dari cookie 'wordpress_logged_in'

9

Saya bekerja dengan klien dengan beberapa langkah keamanan yang ketat. Setelah menjalani tinjauan keamanan, kami diberitahu bahwa nama pengguna disimpan dalam cookie yang masuk, misalnya

wordpress_logged_in[username]|[hash]

adalah sesuatu yang harus dihapus. Karena ini merupakan bagian integral dari sistem login, saya tidak yakin bagaimana menghapusnya dan masih mempertahankan sesi.

phatskat
sumber

Jawaban:

10

Pengantar singkat

Setelah melihat sekilas ke dalam kode sumber WP, saya pikir saya telah menemukan solusi ...

WordPress menggunakan dua fungsi untuk mengatur dan mengurai cookie auth:

  • wp_generate_auth_cookie
  • wp_parse_auth_cookie

Ada filter yang wp_generate_auth_cookiedisebut auth_cookieyang mungkin bisa Anda gunakan untuk mengubah konten cookie, tetapi tidak ada filter di dalamnya wp_parse_auth_cookie, tetapi ...

Kedua fungsi ini didefinisikan dalam pluggable.php, yang berarti, Anda dapat menulis implementasi Anda sendiri untuk mereka dan menimpa yang default.

Larutan

  1. Tulis plugin Anda sendiri (sebut saja Cookie Better Auth)
  2. Terapkan fungsi Anda sendiri wp_generate_auth_cookiedan wp_parse_auth_cookiedi dalam plugin ini.
  3. Aktifkan plugin Anda.

Anda dapat menemukan implementasi sampel saya (berdasarkan versi asli) dari fungsi-fungsi berikut:

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;

Versi saya dari fungsi-fungsi ini diganti user_logindengan user_id. Tapi itu harus menjadi awal yang baik untuk mengubahnya menjadi sesuatu yang lebih kompleks (yaitu hash khusus pengguna, atau sesuatu seperti ini).

Krzysiek Dróżdż
sumber
Jawaban bagus. Padahal aku akan menunggu sampai hari terakhir masa hikmahku. :)
Anonymous Platypus
Saya akan menerima ini, meskipun saya tidak akan mengujinya karena saya tidak lagi membutuhkan solusi ini. Anda jelas-jelas berupaya keras untuk menggali akar sistem, saya menghargai usaha :)
phatskat
1
Meskipun pendekatan ini bagus, Anda harus sadar bahwa itu tidak memberikan perlindungan lagi. Nama pengguna diganti untuk ID pengguna, tetapi nama pengguna dapat diperoleh dari ID pengguna melalui permintaan example.com?author=123, yang melakukan pengalihan kanonik ke URL seperti example.com/author/john.
John Blackbourn
1
@ John tolong baca dengan cermat. Saya telah menyebutkan, bahwa Anda dapat dengan mudah membuatnya lebih aman menyimpan beberapa hash acak dalam cookie daripada userID.
Krzysiek Dróżdż