通过AJAX提交数据属性数据是否存在安全风险?

时间:2016-08-09 作者:Swen

我写了一个简单的作者订阅插件。基本上,它显示了一个类似于YouTube的订阅按钮。当一个(登录的)用户点击它时,他们会订阅该作者,并会收到他们帖子的通知。

我使用AJAX使按钮不刷新页面,并使用数据属性将作者ID发送到我的函数,但我不确定这种方法是否会带来任何风险。

<button class="subscribe_button" data-author-id="352" data-action="subscribe">
从理论上讲,是否有人可以更改此数据属性的值以导致SQL注入或其他操作?通过AJAX发布数据似乎非常容易受到攻击,这比仅仅是一个PHP文件更容易受到攻击。我有理由这样想吗?下面的代码是否有任何风险?

<script>        
    ( function( $ ) {

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

        $(subscriptions_container).on(\'click\', \'.subscribe_button\', function() {                    

            // Disable button temporarily
            $(this).unbind("click");

            var thisButton = $(this);

            // Define author_id and button action
            var author_id = $(this).data( "author-id"),
                action = $(this).data( "action") + \'_callback\';

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

            // Send data with AJAX
            jQuery.post(ajaxurl, data, function(response) {
                thisButton.closest(\'.subscriptions\').replaceWith(response);
            });
        });
    } )( jQuery );
</script>
和我的PHP回调函数:

function subscribe_callback() {
    check_ajax_referer( \'*****\', \'security\' );

    if ( is_user_logged_in() ) {                
        global $wpdb;
        $table_name = $wpdb->prefix . "subscriptions";

        // Check if author_id is posted and if it\'s a number
        if ( isset($_POST[\'author_id\']) && is_numeric($_POST[\'author_id\'])  ) {
            $author_id = $_POST[\'author_id\'];
            $subscriber_id = get_current_user_id(); 

            // check if author is not subscribing to himself, if not then add database query
            if ( $author_id != $subscriber_id ) {
                if ( $wpdb->insert(
                    $table_name,
                    array(
                        \'subscriber_user_id\' => $subscriber_id,
                        \'author_user_id\' => $author_id,
                        \'email_notification\' => \'yes\',
                        \'subscription_date\' => current_time( \'mysql\' )
                    ),
                    array(
                        \'%d\',
                        \'%d\',
                        \'%s\',
                        \'%s\'
                    )
                ) !== FALSE ) {
                    // add subscriber to usermeta
                    $author_subscriber_count = get_user_meta($author_id, \'subscribers\', true);
                    $author_subscriber_count++; 
                    update_user_meta($author_id, \'subscribers\', $author_subscriber_count);  

                    echo subscribe_button($author_id);          
                }
            }
        }
    }

    wp_die();
} add_action( \'wp_ajax_subscribe_callback\', \'subscribe_callback\' );

3 个回复
SO网友:Andrei

在处理提交表单时,即使它们是用AJAX发送的,也必须按照Never trust user\'s input 规则

每一个data-attribute 可以通过Inspector进行更改和编辑。您的唯一可信验证应该在服务器端,就像您在以下方面所做的那样:

if ( isset($_POST[\'author_id\']) || is_numeric($_POST[\'author_id\']) )
就我个人而言,我会颠倒逻辑,首先检查所有属性,然后再开始任何操作。

check_ajax_referer( \'*****\', \'security\' );

if ( ! isset($_POST[\'author_id\']) && ! is_numeric($_POST[\'author_id\']) ) {
      // tell the villain that this tower is watched
      wp_send_json_error( \'Wrong author ID!\' );
}

// now is safe to cache
$author_id = $_POST[\'author_id\'];
被盗自Codex.

这些参数是通过URI编码传递的,所以我不会太担心数据类型或转换。

SO网友:David

不,这并不比通过URL参数或HTML表单发送的POST请求从用户处排除数据风险大或小。对于所有这些方法,Andrei Lupu已经提到的规则适用:Consider each input as possibly harmful.

为了保护您的系统,如果可能的话,您应该首先根据您的期望验证输入。E、 g.您知道用户ID将始终是数字。验证后,必须对上下文更改中的特殊字符进行转义。如果要将字符串用作SQL查询的一部分,这是一种上下文更改,因此必须对SQL上下文中具有特殊含义的字符进行转义。就你而言,wpdb::insert() 为你做这件事。

另一种可能的上下文更改是,如果您想在HTML上下文中直接使用用户输入(将其打印到模板中)。

客户机-服务器应用程序中的另一个重要步骤是验证该命令实际上是用户想要的。否则,请打开应用程序cross-side request forgery (CSRF) 攻击。由于您(显然)使用WordPress的nonce函数,并且该功能仅对登录用户可用,因此您的命令经过了相当的验证。

因此,从今天的角度来看,您的代码示例被认为是安全的。

SO网友:Krzysztof Grabania

可以很容易地覆盖数据属性,例如通过jQuery函数data. 例如,我将使用从用户id和登录名生成的md5对属性执行此操作$user_id . \'-\' . md5($user_id . $user_login). php脚本应通过以下方式检查用户:

分解属性- 签名

  • 按id获取用户(之前-签名)

    生成md5并将其与之后的值进行比较- 签名

  • 相关推荐

    尝试在WordPress中实现AJAX注释,遇到WP错误

    我试图在WordPress中为我的评论实现Ajax,使用this tutorial. 但我在将教程中的代码集成到自己的预构建主题时遇到了问题。问题是,我要么得到一个WP错误“检测到重复注释;看来你已经说过了!”或标准500错误。以下是我得到的:下面是我对ajax的评论。js文件如下所示: * Let\'s begin with validation functions */ jQuery.extend(jQuery.fn, { /* * check i