WordPress‘is_user_loged_in()安全吗?

时间:2013-07-07 作者:Frederick Andersen

我一直在想这件事有一段时间了。是以下内容if 声明是否足够安全?在未登录时,是否很容易突破代码并访问内容?

<?php if ( is_user_logged_in() ) { 
     // SECURE CONTENT
} else { 
     // LANDING PAGE
} ?>

3 个回复
最合适的回答,由SO网友:s_ha_dum 整理而成

那么,你必须问自己“安全到什么程度?”我怀疑您是一家需要极高安全性的银行或其他机构。如果你是,你会有一个每年10万美元以上的专家团队为你回答这个问题。

考虑到这一点。。。

您必须破坏WordPress登录系统才能通过该代码。我相信这是可能的,但如果你的密码是可靠的,这应该是相当困难的。这不会是一种“在查询字符串中放入空字节”的黑客行为。对于大多数用途,它应该足够安全。

需要担心的是is_user_logged_in, 和wp_get_current_user 这取决于,are both pluggable (在我看来这是荒谬的)这意味着一个恶意插件,或者仅仅是一个写得很糟糕的插件,可能会完全破坏您的安全。

SO网友:Stephen Harris

简而言之,对于一般用途来说,是的。正如@s\\u ha\\u dum所指出的,这实际上取决于您使用它的目的。

功能是否安全

正如@kaiser和@s\\u ha\\u dum所提到的,该功能是可插入的-这意味着任何插件(尽管不是主题)都可以重新定义它来做任何事情。但这并不是一个真正的问题,因为插件几乎可以做任何事情——它们正在您的服务器上执行代码。

事实上,它的“可插拔”并不是这里真正的问题。你应该确保你使用的所有插件和主题都可以被合理地信任。在安全性至关重要的地方,公司往往会创建自己的插件,并且只使用这些插件。

(事实上,它是可插拔的,因此如果需要的话,公司可以实施更安全的认证系统)。

身份验证方法是否安全

让我们假设函数是在WordPress核心中定义的。安全吗?(是)。

这个is_user_logged_in() 函数检查用户浏览器中是否存在有效的cookie。如果不存在、无效或已过期,他们将被迫重新登录。

cookie由以下内容生成:

用户的用户名从其密码哈希中提取8个字符,用于cookie过期时的时间戳,cookie本身以明文形式包含用户名和时间戳。它还包含一个HMAC(hash message authentication code) - 这一部分很难猜测,并且取决于用户名&;时间戳。因此,如果攻击者持有过期的cookie,或他们自己帐户的cookie,他们无法生成有效的cookie,在不生成有效HMAC的情况下将其登录到管理员帐户。

HMAC由上述3个元素的哈希生成。现在,8个角色似乎并不多——这可能是一周内的野蛮强迫。但事实上,哈希是salted hash - 使用站点的盐。这样,只要他们安全,任何暴力强迫的企图都会被挫败。

。。。因此,该功能的安全性实际上取决于网站盐类的安全性。这些存储在wp-config.php, 以及您的数据库凭据。You should never make that public.

我是否可以检测函数是否更改了可插入函数的定义

只有当MU插件覆盖了一个函数时,上述Kaiser函数才起作用。这里有一个更通用的解决方案,声明不覆盖可插入函数的插件是not 表明插件是安全的。

/**
 * Do not use in production.
 * 
 * Checks if any plug-ins have overwritten a pluggable function in 
 * `wp-includes/pluggable.php` with a custom function.
 * 
 * Prints list and kills processing if a function has been overwritten.
 * 
 * Based on Kaiser\'s answer (link below).
 * @link http://wordpress.stackexchange.com/questions/105637/is-wordpress-is-user-logged-in-secure/105667#105667
 */
function wpse105637_was_pluggable_defined_by_plugin(){

    $arr = token_get_all( file_get_contents( ABSPATH.WPINC.\'/pluggable.php\' ) );
    $functions = array();
    foreach ( $arr as $curr_key => $part ){
        if ( ! is_array( $part ) )
            continue;

        if ( token_name( $part[0] ) === \'T_FUNCTION\' ){
            while ( is_array( $arr[ $curr_key ] ) AND \'T_FUNCTION\' !== $arr[ $curr_key ][0] )
                ++$curr_key;
            $functions[] = $arr[ --$curr_key ][1];
        }
    }

    $overwritten  = 0;
    foreach ( $functions as $f ){
        $reflFunc = new ReflectionFunction( $f );
        if( ABSPATH.WPINC.\'/pluggable.php\' !== $reflFunc->getFileName() ){
            $overwritten++;
            printf( \'<h1> Functions Overwritten </h1>\' );
            print \'<code>\'.$f .\'</code> \' . $reflFunc->getFileName() . \':\' . $reflFunc->getStartLine() . \'<br/>\';
        }
    }

    if( $overwritten )
        wp_die( sprintf( \'%d pluggable functions overwritten\', $overwritten ) );

}
add_action( \'plugins_loaded\', \'wpse105637_was_pluggable_defined_by_plugin\' );

SO网友:kaiser

可插拔功能首先,可插拔功能是从~/wp-settings.php 文件它们是在包含所有插件文件之后才包含的(但在之前)plugins_loaded) 所以任何插件都可以替代它们。(mu插件包含得更早,所以它们优先)。

黑客的障碍默认用户永远不会担心这一点,因为他甚至可能没有muplugins文件夹,因为默认情况下它不是由core添加的。因此,“黑客”需要做的第一件事就是实际添加文件夹。这意味着他已经可以访问您的文件系统,而您遇到的问题与您安装的系统上的黑客完全不同。当每一扇更容易接近的门都敞开时,没有哪个严肃的黑客会为WordPress而烦恼。所以只要检查一下WPMU_PLUGIN_DIRWPMU_PLUGIN_URL 已定义。如果不是,你就不用担心了。

接下来,如果你有一个muplugins文件夹,你要做的就是检查这些文件。这很容易:MU插件只能作为单文件插件工作。因此,如果您的插件多于文件,那么您的文件中就有一个以上已经加载了外部文件。您可以通过使用get_included_files()muplugins_loaded 优先挂钩0, 然后在plugins_loaded-挂接优先级0. 差值必须等于你从中得到的结果

count( glob( WPMU_PLUGIN_DIR.\'/*.php\' ) );
最后要担心的事

那么,假设有人真的成功地将一个MU插件交给了你(在你自己添加文件夹后,你必须自己安装),那么现在是时候监控是否有一个可插入功能被替换了。您可以使用下面的插件来执行此操作。它只会die() 在任何情况下,如果您的一项功能被替换,“保护”您和您的访客。它以最晚的可能时间(钩子优先级中没有真正的“最新”),读取可插入文件中的所有函数,然后检查它们是否存在。由于它只获取文件的内容,因此不会包含它,因此不会定义这些函数。通过这种方式,您可以确保MU插件始终保持最新,因为函数的数量可能会发生变化,但插件仍然知道它。

请记住,插件至少需要PHP 5.3版。

<?php
defined( \'ABSPATH\' ) OR exit;
/**
 * Plugin Name: (#105637) Check pluggable changes
 */
add_action( \'muplugins_loaded\', \'wpse_pluggable_check\', pow( 99, 99 ) );
function wpse_pluggable_check()
{
    $arr = token_get_all( file_get_contents( ABSPATH.WPINC.\'/pluggable.php\' ) );
    $functions = array();
    foreach ( $arr as $curr_key => $part )
    {
        if ( ! is_array( $part ) )
            continue;

        $token = token_name( array_shift( $part ) );
        $token === \'T_FUNCTION\'
            AND $functions[] = $arr[ $curr_key + 2 ][1];
    }
    foreach ( $functions as $f )
        function_exists( $f ) AND wp_die( \'pluggable overwritten!\' );
}
上述插件假设函数方案始终为function fn_name() {. 这里有一个稍微增强的版本,它搜索以下数组。

$arr = token_get_all( file_get_contents( ABSPATH.WPINC.\'/pluggable.php\' ) );
$functions = array();
foreach ( $arr as $curr_key => $part )
{
    if ( ! is_array( $part ) )
        continue;

    if ( token_name( $part[0] ) === \'T_FUNCTION\' )
    {
        while ( is_array( $arr[ $curr_key ] ) AND \'T_FUNCTION\' !== $arr[ $curr_key ][0] )
            ++$curr_key;
        $functions[] = $arr[ --$curr_key ][1];
    }
}
foreach ( $functions as $f )
    function_exists( $f ) AND wp_die( \'pluggable overwritten!\' );

结束

相关推荐