如何检查是否正确实现了AJAX随机数?

时间:2017-03-30 作者:Swen

我有一个简单的“favorite post”按钮,可用于AJAX。我知道使用WordPress nonce可以提高安全性,但我不太清楚它为什么或者如何做到这一点。这也使我无法检查是否正确、安全地实现了nonce。

jQuery Script

function favorites_javascript() {       
    $ajax_nonce = wp_create_nonce( "ajax-nonce-favorites" );

    ?>

    <script>
        ( function( $ ) {               
            var ajaxurl = "<?php echo admin_url(\'admin-ajax.php\'); ?>";

            // ...

            // Data to be sent to function
            var data = {
                \'action\': \'favorites_callback\',
                \'security\': \'<?php echo $ajax_nonce; ?>\',

                \'post_id\': post_id,
                \'button_action\' : button_action
            };

            // Send Data
            jQuery.post(ajaxurl, data, function(response) {     

                // ...

            });

            // ...

        } )( jQuery );
    </script> 

    <?php
} add_action( \'wp_footer\', \'favorites_javascript\' );

PHP Callback

function favorites_callback() {
    check_ajax_referer( \'ajax-nonce-favorites\', \'security\' );

    if ( !is_user_logged_in() ) {
        wp_send_json_error( \'Error!\' );
    }

    // Process Data

    wp_die();
} add_action( \'wp_ajax_favorites_callback\', \'favorites_callback\' );
这是WordPress nonce for AJAX的正确实现吗?我如何“测试”这段代码,以查看nonce是否工作且安全?

2 个回复
最合适的回答,由SO网友:Mark Kaplun 整理而成

您的代码在某些微妙的方面是不正确的,但要了解为什么我们首先需要回到wordpress中的nonce以及它能保护什么。

根据常见定义,Nonce是一个仅使用一次的数字,用于对抗重播攻击。在重播攻击中,您只是重播事务(http请求),而不了解其组件以重做用户操作。一个简单的例子是,如果有人可以重播你的购物订单,并导致你在没有你参与的情况下订购更多相同的东西,这可能会导致糟糕的情况。您使用其他人的网络的典型情况(不确定SSL是否有帮助)。

人们还发现,nonce是避免CSRF 攻击,因为很难预测攻击者应该使用的URL/参数。

在wordpress中,重要性的顺序是颠倒的,首要的是打击CSRF攻击,而打击重播攻击只是次要的。这导致wordpress nonces是一个“每天唯一”的数字,而不是经典的“一次性”数字。

那么wordpress如何使用nonce来保护CSRF呢?它根据上下文生成nonce。您可以在wp_create_nonce 密码

function wp_create_nonce($action = -1) {
    $user = wp_get_current_user();
    $uid = (int) $user->ID;
    if ( ! $uid ) {
        /** This filter is documented in wp-includes/pluggable.php */
        $uid = apply_filters( \'nonce_user_logged_out\', $uid, $action );
    }

    $token = wp_get_session_token();
    $i = wp_nonce_tick();

    return substr( wp_hash( $i . \'|\' . $action . \'|\' . $uid . \'|\' . $token, \'nonce\' ), -12, 10 );
}
上下文是操作名称、用户id和当前登录会话,这确保了将为不同的操作、不同的用户甚至同一用户的不同会话生成不同的nonce,因此,即使有人知道在使用自己的用户执行操作(比如删除帖子)时用于执行操作的nonce,他无法通过构造具有相同nonce的特殊URL来欺骗您删除帖子。

这是你的第一个错误(很多人都会这样做),那就是试图对未登录的用户应用nonce。如果没有用户上下文,整个nonce都是从操作派生的,“攻击者”可以共享相同的url,供未登录的用户(或机器人)使用。

How to test that your code works correctly in preventing CSRF? 如果它是一个简单的URL,请在以其他用户身份登录时尝试重新发送它。处理url本身包含nonce的请求更容易,但可能可以使用浏览器开发人员工具(更改身份验证cookie并重新发送)或curl/wget来完成。

您编写代码所缺乏的另一部分是针对某种重播攻击的保护。假设我知道你喜欢帖子X,我是否可以重新传输请求并使其看起来像你也喜欢帖子Y?现在我要做的就是改变post_id 请求的参数。

防止此类攻击的方法是action nonce的一部分是动态的,并以某种方式包括重要参数,在您的情况下是post id。Core通常使用此类操作delete-post-{post_id} 这将确保为不同的帖子生成不同的nonce。

How to test? 使用浏览器开发人员工具,更改post id参数,以确保相同的nonce不能用于收藏不同的帖子。

For phpunit type of testing 您可能需要编写自己的nonce生成器来包装wordpress核心nonce函数,并检查它们是否为不同的用户、不同的会话、不同的操作和不同的密钥请求参数提供相同的nonce。

SO网友:Fabrizio Mele

WP Codex 似乎实施是正确的。

一个简单的测试是生成一个没有security 中的参数$.ajax(), 或者使用来自不同时间和页面的nonce发出相同的请求。

(什么是nonce,仅供参考:wiki)

相关推荐

无法使用AJAX访问数据库中的数据

我正试图在wordpress中首次调用AJAX。我遵循了一些教程,到目前为止已经达到了这一点。但当我试图安慰的时候。将从数据库中获取的数据记录在AJAX调用中,我发现以下错误:未捕获引用错误:未定义数据代码:功能。phpfunction my_ajax_handler(){ global $wpdb; $name = $wpdb->get_results(\"SELECT * FROM username\"); echo $name;