web-dev-qa-db-fra.com

Contourner les publications protégées par mot de passe via la variable GET

J'aime contourner la forme de mot de passe des publications protégées avec une variable GET avec les conditions suivantes:

  • Aucun changement au coeur
  • Aucune exposition claire du mot de passe (hachage)
  • Aucune fuite de sécurité

Aucune modification du noyau

C'est une évidence car la fonctionnalité devrait être dans un plugin et fonctionner en sortie de boîte. J'ai trouvé quelques méthodes qui modifie le fichier core.

Pas d'exposition claire du mot de passe

Au lieu de http://example.com/post?pwd=mypassword, l'URL devrait ressembler à http://example.com/post?pwd=%25P%25BaxfPUloy8YdOFi2F9F2xAcCg8OLGP

Pas de fuites de sécurité possibles

Bien sûr, cela ne devrait pas être "piraté" d'une manière ou d'une autre. Ce ne sont que des messages protégés, mais il s’agit néanmoins d’un non-lieu.

Ce dont j'ai besoin:

Une façon d'obtenir le hachage ajouté à l'URL:

$url = add_query_arg(array(
    'pwd' => get_my_hash();
), get_permalink($post_id));

et sur le modèle de page le code:

if(post_password_required()){
    if(isset($_GET['pwd'])){
        if(check_pwd_with_hash($_GET['pwd'])){
        //unlock content
        }
    }
}

the_content();

Il n'y a aucun moyen de se connecter à la méthode post_password_required() ou de définir simplement le $post->post_password global sur une chaîne vide.

5
Xaver

La vérification de la publication d'un mot de passe a lieu (pour une raison quelconque) dans get_the_content(), qui semble légitime, mais mélange en réalité deux préoccupations distinctes. Vous aviez raison avec l'affirmation qu'il n'y a aucun moyen de contourner get_the_content() en affichant le formulaire de mot de passe. Voici ce que la vérification du mot de passe fait en détail:

if ( empty( $post->post_password ) )
     return false;

if ( ! isset( $_COOKIE['wp-postpass_' . COOKIEHASH] ) )
     return true;

require_once ABSPATH . WPINC . '/class-phpass.php';
$hasher = new PasswordHash( 8, true );
$hash = wp_unslash( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] );
if ( 0 !== strpos( $hash, '$P$B' ) )
     return true;
return ! $hasher->CheckPassword( $post->post_password, $hash );

Comme vous pouvez le constater, le mot de passe est vérifié par rapport à un Cookie stocké sur l'ordinateur de l'utilisateur.

Pour contourner le mot de passe de publication, vous devrez en fait donner à l'utilisateur une autorisation explicite en définissant ce cookie. Core le fait de la manière suivante:

setcookie(
    'wp-postpass_' . COOKIEHASH,
    $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ),
    $expire,
    COOKIEPATH
);

quand vous regardez the_post_password() , qui est utilisé pour récupérer le (mot de passe en texte brut), vous constaterez qu'il ne fait rien à part d'échapper à l'argument pour la sécurité des utilisateurs:

esc_attr( $post->post_password )

Maintenant, vous pouvez combiner cela et définir le cookie before vous affichez le contenu dans votre modèle:

// Your custom check for the `$_GET` content
// …also check if there in fact is a password
// …and if the user is a repeated visitor, do not set the Cookie again
if (
        isset( $_GET['circumvent'] ) 
        and 'disable-pass' === $_GET['circumvent'] 
        and isset( $post->post_password )
        and ! isset( 'wp-postpass_'.COOKIEHASH )
    ) {
    // Finally we use the plain text password to set the Cookie
    // as if the user would have entered it into the password form
    setcookie(
        'wp-postpass_'.COOKIEHASH,
        $hasher->HashPassword( wp_unslash( esc_attr( $post->post_password ) ) ),
        $expire,
        COOKIEPATH
    );
}
// Now display the content:
the_content();

Informations complémentaires informations à propos des mots de passe postaux Dans cet article, j’ai écrit que ce concept est très peu connu et que vous voudrez peut-être prendre en compte certains de ces détails.

5
kaiser