Plugin Directory

Changeset 3669794


Ignore:
Timestamp:
08/28/2026 04:57:55 AM (2 months ago)
Author:
sstoqnov
Message:

Bump to 1.6.7

Location:
sg-security/trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • sg-security/trunk/core/Loader/Loader.php

    r3666555 r3669794  
    340340                add_action( 'wp_login', array( $this->sg_2fa, 'move_encryption_file' ), 9, 2 );
    341341                add_action( 'wp_login', array( $this->sg_2fa, 'init_2fa' ), 10, 2 );
     342                add_filter( 'authenticate', array( $this->sg_2fa, 'block_xmlrpc_for_2fa_users' ), 99, 1 );
    342343                add_action( 'login_form_sgs2fa', array( $this->sg_2fa, 'validate_2fa_login' ) );
    343344                add_action( 'login_form_sgs2fabc', array( $this->sg_2fa, 'validate_2fabc_login' ) );
  • sg-security/trunk/core/Sg_2fa/Sg_2fa.php

    r3592620 r3669794  
    455455                }
    456456
    457                 // Parse the cookie.
     457                // Parse the cookie into the user ID and the token.
    458458                $cookie_data = explode( '|', $_COOKIE[ $sg_2fa_user_cookie ] );
    459459
    460                 if (
    461                         // If the 2FA is configured for the user.
    462                         1 == get_user_meta( $cookie_data[0], 'sg_security_2fa_configured', true ) && // phpcs:ignore
    463                         get_user_meta( $cookie_data[0], 'sgs_2fa_dnc_token', true ) === $cookie_data[1]  && // If there is already a cookie with that name and the name matches.
    464                         (int) $cookie_data[0] === (int) $user->ID // If the cookie ID matches the logging in user ID.
    465                 ) {
    466                         return true;
    467                 }
    468 
    469                 return false;
     460                // Bail if the cookie is malformed. It must be exactly "<user_id>|<token>" with both parts present.
     461                if ( 2 !== count( $cookie_data ) || '' === $cookie_data[0] || '' === $cookie_data[1] ) {
     462                        return false;
     463                }
     464
     465                // Bail if the cookie user ID does not match the logging in user ID.
     466                if ( (int) $cookie_data[0] !== (int) $user->ID ) {
     467                        return false;
     468                }
     469
     470                // Bail if the 2FA is not configured for the user.
     471                if ( 1 != get_user_meta( $cookie_data[0], 'sg_security_2fa_configured', true ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
     472                        return false;
     473                }
     474
     475                // Bail if the user has no stored token. An absent single-value meta returns an empty
     476                // string, which must never be treated as a match for an empty cookie token.
     477                if ( ! metadata_exists( 'user', (int) $cookie_data[0], 'sgs_2fa_dnc_token' ) ) {
     478                        return false;
     479                }
     480
     481                // Get the stored 'do not challenge' token for the user.
     482                $stored_token = get_user_meta( $cookie_data[0], 'sgs_2fa_dnc_token', true ); // phpcs:ignore
     483
     484                // Bail if the stored token is empty.
     485                if ( '' === $stored_token ) {
     486                        return false;
     487                }
     488
     489                // Constant-time comparison of the stored token against the supplied cookie token.
     490                return hash_equals( (string) $stored_token, (string) $cookie_data[1] );
    470491        }
    471492
    … …  
    525546                <?php
    526547                exit;
     548        }
     549
     550        /**
     551         * Block XML-RPC password authentication for users who are in 2FA scope.
     552         *
     553         * @since  1.6.6
     554         *
     555         * @param  null|\WP_User|\WP_Error $user The authenticated user, a WP_Error, or null.
     556         * @return null|\WP_User|\WP_Error       WP_Error to block, otherwise $user unchanged.
     557         */
     558        public function block_xmlrpc_for_2fa_users( $user ) {
     559                // Only act on XML-RPC requests; leave every other auth path untouched.
     560                if ( ! defined( 'XMLRPC_REQUEST' ) || ! XMLRPC_REQUEST ) {
     561                        return $user;
     562                }
     563
     564                // Let core's own failures/short-circuits stand; only act on a resolved user.
     565                if ( ! ( $user instanceof \WP_User ) ) {
     566                        return $user;
     567                }
     568
     569                // Allow users who are not in 2FA scope (e.g. subscribers) to keep using XML-RPC.
     570                if ( empty( array_intersect( $this->get_admin_user_roles(), $user->roles ) ) ) {
     571                        return $user;
     572                }
     573
     574                // Escape hatch for sites that intentionally rely on XML-RPC for covered users.
     575                if ( ! apply_filters( 'sg_security_2fa_block_xmlrpc', true, $user ) ) {
     576                        return $user;
     577                }
     578
     579                // Reject: wp_xmlrpc_server::login() turns this into a 403 fault before
     580                // wp_set_current_user() runs, so no authenticated session is created.
     581                return new \WP_Error(
     582                        'sgs_2fa_xmlrpc_blocked',
     583                        __( 'XML-RPC authentication is disabled for accounts that require 2-factor authentication.', 'sg-security' )
     584                );
    527585        }
    528586
  • sg-security/trunk/readme.txt

    r3666555 r3669794  
    55Tested up to: 7.1
    66Requires PHP: 7.0
    7 Stable tag: 1.6.6
     7Stable tag: 1.6.7
    88License: GPLv3
    99License URI: http://www.gnu.org/licenses/gpl-3.0.html
    … …  
    144144
    145145== Changelog ==
     146= Version 1.6.7 =
     147Release Date Aug 28th, 2026
     148
     149* Security Improvements
     150
    146151= Version 1.6.6 =
    147152Release Date Aug 26th, 2026
  • sg-security/trunk/sg-security.php

    r3666555 r3669794  
    1111 * Plugin URI:        https://siteground.com
    1212 * Description:       Security Optimizer by SiteGround is the all-in-one security solution for your WordPress website. With the carefully selected and easy to configure functions the plugin provides everything you need to secure your website and prevent a number of threats such as brute-force attacks, compromised login, data leaks and more.
    13  * Version:           1.6.6
     13 * Version:           1.6.7
    1414 * Author:            SiteGround
    1515 * Author URI:        https://www.siteground.com
    … …  
    3333// Define version constant.
    3434if ( ! defined( __NAMESPACE__ . '\VERSION' ) ) {
    35         define( __NAMESPACE__ . '\VERSION', '1.6.6' );
     35        define( __NAMESPACE__ . '\VERSION', '1.6.7' );
    3636}
    3737
  • sg-security/trunk/vendor/autoload.php

    r3495512 r3669794  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInitc293d1e978bd19a1e0aed5fa8f47c860::getLoader();
     22return ComposerAutoloaderInit0bdd2490f3df64761a8cfea216f31e5d::getLoader();
  • sg-security/trunk/vendor/composer/autoload_psr4.php

    r2796592 r3669794  
    1010    'SiteGround_Helper\\' => array($vendorDir . '/siteground/siteground-helper/src'),
    1111    'SiteGround_Emails\\' => array($vendorDir . '/siteground/siteground-emails/src'),
    12     'SiteGround_Data\\' => array($vendorDir . '/siteground/siteground-data/src'),
    1312    'SG_Security\\' => array($baseDir . '/core'),
    1413    'PragmaRX\\Recovery\\' => array($vendorDir . '/pragmarx/recovery/src'),
  • sg-security/trunk/vendor/composer/autoload_real.php

    r3091354 r3669794  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitc293d1e978bd19a1e0aed5fa8f47c860
     5class ComposerAutoloaderInit0bdd2490f3df64761a8cfea216f31e5d
    66{
    77    private static $loader;
    … …  
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitc293d1e978bd19a1e0aed5fa8f47c860', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit0bdd2490f3df64761a8cfea216f31e5d', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitc293d1e978bd19a1e0aed5fa8f47c860', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit0bdd2490f3df64761a8cfea216f31e5d', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d::getInitializer($loader));
    3333
    3434        $loader->register(true);
  • sg-security/trunk/vendor/composer/autoload_static.php

    r3495512 r3669794  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860
     7class ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d
    88{
    99    public static $prefixLengthsPsr4 = array (
    … …  
    1313            'SiteGround_Helper\\' => 18,
    1414            'SiteGround_Emails\\' => 18,
    15             'SiteGround_Data\\' => 16,
    1615            'SG_Security\\' => 12,
    1716        ),
    … …  
    4140        array (
    4241            0 => __DIR__ . '/..' . '/siteground/siteground-emails/src',
    43         ),
    44         'SiteGround_Data\\' =>
    45         array (
    46             0 => __DIR__ . '/..' . '/siteground/siteground-data/src',
    4742        ),
    4843        'SG_Security\\' =>
    … …  
    9085    {
    9186        return \Closure::bind(function () use ($loader) {
    92             $loader->prefixLengthsPsr4 = ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860::$prefixLengthsPsr4;
    93             $loader->prefixDirsPsr4 = ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860::$prefixDirsPsr4;
    94             $loader->prefixesPsr0 = ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860::$prefixesPsr0;
    95             $loader->classMap = ComposerStaticInitc293d1e978bd19a1e0aed5fa8f47c860::$classMap;
     87            $loader->prefixLengthsPsr4 = ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d::$prefixLengthsPsr4;
     88            $loader->prefixDirsPsr4 = ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d::$prefixDirsPsr4;
     89            $loader->prefixesPsr0 = ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d::$prefixesPsr0;
     90            $loader->classMap = ComposerStaticInit0bdd2490f3df64761a8cfea216f31e5d::$classMap;
    9691
    9792        }, null, ClassLoader::class);
  • sg-security/trunk/vendor/composer/installed.json

    r3495512 r3669794  
    451451        },
    452452        {
    453             "name": "siteground/siteground-data",
    454             "version": "dev-master",
    455             "version_normalized": "dev-master",
    456             "source": {
    457                 "type": "git",
    458                 "url": "git@gitlab.siteground.com:wordpress/siteground-data.git",
    459                 "reference": "9716965f513427cc017f787b43531c437227021d"
    460             },
    461             "require": {
    462                 "siteground/siteground-helper": "master@dev"
    463             },
    464             "time": "2026-02-25T15:08:41+00:00",
    465             "default-branch": true,
    466             "type": "library",
    467             "installation-source": "source",
    468             "autoload": {
    469                 "psr-4": {
    470                     "SiteGround_Data\\": "src/"
    471                 }
    472             },
    473             "authors": [
    474                 {
    475                     "name": "Stanimir Stoyanov",
    476                     "email": "stanimir.stoyanov@siteground.com"
    477                 }
    478             ],
    479             "install-path": "../siteground/siteground-data"
    480         },
    481         {
    482453            "name": "siteground/siteground-emails",
    483454            "version": "dev-master",
  • sg-security/trunk/vendor/composer/installed.php

    r3495512 r3669794  
    44        'pretty_version' => 'dev-develop',
    55        'version' => 'dev-develop',
    6         'reference' => '866b342b625a5f2fde85c7ea4a23155fa89c6824',
     6        'reference' => 'bd34eb1c269c7c940e435d7786d5c4023d6877a8',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    8484            'pretty_version' => 'dev-develop',
    8585            'version' => 'dev-develop',
    86             'reference' => '866b342b625a5f2fde85c7ea4a23155fa89c6824',
     86            'reference' => 'bd34eb1c269c7c940e435d7786d5c4023d6877a8',
    8787            'type' => 'wordpress-plugin',
    8888            'install_path' => __DIR__ . '/../../',
    8989            'aliases' => array(),
    90             'dev_requirement' => false,
    91         ),
    92         'siteground/siteground-data' => array(
    93             'pretty_version' => 'dev-master',
    94             'version' => 'dev-master',
    95             'reference' => '9716965f513427cc017f787b43531c437227021d',
    96             'type' => 'library',
    97             'install_path' => __DIR__ . '/../siteground/siteground-data',
    98             'aliases' => array(
    99                 0 => '9999999-dev',
    100             ),
    10190            'dev_requirement' => false,
    10291        ),
  • sg-security/trunk/vendor/siteground/siteground-emails/src/Email_Service.php

    r3523445 r3669794  
    8888         */
    8989        protected $sg_mail_from_name;
    90 
    91         /**
    92          * Mail From Email Address.
    93          *
    94          * @since  1.6.1
    95          *
    96          * @var    string
    97          * @access protected
    98          */
    99         protected $sg_mail_from_address = false;
    10090
    10191        /**
    … …  
    161151                        add_filter( 'wp_mail_from_name', array( $this, 'set_mail_from_name' ) );
    162152                }
    163 
    164                 // Set a same-domain email address as the From address.
    165                 $this->set_default_from_mail_address();
    166153
    167154                // Sent the email.
    … …  
    173160                );
    174161
    175                 // Remove the default From mail address.
    176                 $this->remove_default_from_mail_address();
    177 
    178162                // Remove the from name if it is set.
    179163                if ( false !== $this->sg_mail_from_name ) {
    … …  
    229213                return wp_unschedule_event( $timestamp, $this->sg_cron_name );
    230214        }
    231 
    232         /**
    233          * Sets a default From email address.
    234          *
    235          * @since 1.6.1
    236          */
    237         public function set_default_from_mail_address() {
    238                 $host = wp_parse_url( home_url(), PHP_URL_HOST );
    239                 $host = preg_replace( '/^www\./', '', $host );
    240 
    241                 if ( empty( $host ) ) {
    242                         return;
    243                 }
    244 
    245                 // Set the default wp_mail() from address.
    246                 $this->sg_mail_from_address = 'wordpress@' . $host;
    247                 add_filter( 'wp_mail_from', array( $this, 'set_mail_from_address' ), PHP_INT_MAX );
    248 
    249                 // Also set the PHP Mailer from address.
    250                 add_action( 'phpmailer_init', array( $this, 'set_phpmailer_from_address' ), PHP_INT_MAX );
    251         }
    252 
    253         /**
    254          * Removes the default From email address.
    255          *
    256          * @since 1.6.1
    257          */
    258         public function remove_default_from_mail_address() {
    259                 // Remove the PHP Mailer from address first.
    260                 if ( false !== $this->sg_mail_from_address ) {
    261                         remove_action( 'phpmailer_init', array( $this, 'set_phpmailer_from_address' ), PHP_INT_MAX );
    262                 }
    263 
    264                 // Remove the default wp_mail() filter.
    265                 remove_filter( 'wp_mail_from', array( $this, 'set_mail_from_address' ), PHP_INT_MAX );
    266 
    267                 $this->sg_mail_from_address = false;
    268         }
    269 
    270         /**
    271          * Returns the default email address.
    272          *
    273          * @since 1.6.1
    274          *
    275          * @param string $from_email The original From email address.
    276          *
    277          * @return string The default From email address.
    278          */
    279         public function set_mail_from_address( $from_email ) {
    280                 return $this->sg_mail_from_address;
    281         }
    282 
    283         /**
    284          * Sets PHP Mailer from address and force server mail transport instead of configured SMTP.
    285          *
    286          * @since 1.6.1
    287          *
    288          * @param object The PHPMailer object.
    289          */
    290         public function set_phpmailer_from_address( $phpmailer ) {
    291                 if ( ! is_object( $phpmailer ) || ! method_exists( $phpmailer, 'setFrom' ) ) {
    292                         return;
    293                 }
    294 
    295                 // Force local/server mail transport instead of configured SMTP.
    296                 if ( method_exists( $phpmailer, 'isMail' ) ) {
    297                         $phpmailer->isMail();
    298                 }
    299 
    300                 $phpmailer->setFrom(
    301                         $this->sg_mail_from_address,
    302                         $this->sg_mail_from_name,
    303                         true
    304                 );
    305 
    306                 // Force the envelope sender / Return-Path too.
    307                 $phpmailer->Sender = $this->sg_mail_from_address;
    308         }
    309215}
  • sg-security/trunk/vendor/siteground/siteground-helper/src/Helper_Service.php

    r3581706 r3669794  
    267267                return $data;
    268268        }
    269 
    270         /**
    271          * Returns the assets URL.
    272          *
    273          * @return string The URL to the uploads assets.
    274          */
    275         public static function get_assets_url() {
    276                 // Get the uploads data.
    277                 $uploads = wp_upload_dir();
    278 
    279                 // Get the baseurl.
    280                 $baseurl = rtrim( $uploads['baseurl'], '/' );
    281 
    282                 // Add the necessary protocol.
    283                 if ( is_ssl() && 0 === strpos( $baseurl, 'http://' ) ) {
    284                         return str_replace( 'http://', 'https://', $baseurl );
    285                 }
    286 
    287                 return $baseurl;
    288         }
    289269}
Note: See TracChangeset for help on using the changeset viewer.