Plugin Directory

Changeset 3635791


Ignore:
Timestamp:
08/05/2026 08:00:53 PM (3 months ago)
Author:
mohsenr1
Message:

v4.17

Location:
newsletters-lite/trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • newsletters-lite/trunk/helpers/auth.php

    r3621582 r3635791  
    141141                                        break;
    142142                        }
     143
     144                        return true;
    143145                }
    144146
    … …  
    163165                                                setcookie($this -> cookiename, $value, strtotime($days), '/');
    164166                                        } else {
    165                                                 $this -> javascript_cookie($this -> cookiename, $value);
     167                                                return false;
    166168                                        }
    167169
    … …  
    180182                                                setcookie($this -> cookiename, $value, strtotime($days), '/');
    181183                                        } else {
    182                                                 $this -> javascript_cookie($this -> cookiename, $value);
     184                                                $_SESSION[$this -> cookiename] = $value;
     185                                                return false;
    183186                                        }
    184187
    … …  
    228231
    229232        function gen_subscriberauth() {
    230                 $subscriberauth = md5(microtime());
    231                 return $subscriberauth;
     233                if (function_exists('wp_generate_password')) {
     234                        return wp_generate_password(64, false, false);
     235                }
     236
     237                try {
     238                        if (function_exists('random_bytes')) {
     239                                return bin2hex(random_bytes(32));
     240                        }
     241                } catch (Exception $e) {
     242                        // Fall through to OpenSSL below.
     243                }
     244
     245                if (function_exists('openssl_random_pseudo_bytes')) {
     246                        $strong = false;
     247                        $bytes = openssl_random_pseudo_bytes(32, $strong);
     248                        if ($bytes !== false && $strong) {
     249                                return bin2hex($bytes);
     250                        }
     251                }
     252
     253                return wp_hash(uniqid('', true) . wp_rand() . microtime(true));
    232254        }
    233255}
  • newsletters-lite/trunk/includes/checkinit.php

    r3566485 r3635791  
    5656            $this -> add_action('widgets_init', 'widget_register', 10, 1);
    5757            $this -> add_action('wp_head', 'wp_head', 15, 1);
     58            $this -> add_action('template_redirect', 'management_loginauth_redirect', 0, 1);
    5859            $this -> add_action('wp_footer');
    5960            $this -> add_action('admin_footer');
  • newsletters-lite/trunk/models/subscriber.php

    r3303758 r3635791  
    816816
    817817                                                $Turnstile = new Turnstile( $secret );
    818                                                 $result    = $Turnstile->verify( $data['cf-turnstile-response'] ?? '', $this->get_ip_address() );
     818                                                $turnstile_response = isset( $data['cf-turnstile-response'] ) ? $data['cf-turnstile-response'] : '';
     819                                                $result    = $Turnstile->verify( $turnstile_response, $this->get_ip_address() );
    819820
    820821                                                if ( ! $result->success ) {
  • newsletters-lite/trunk/readme.txt

    r3621582 r3635791  
    55Requires at least: 3.8
    66Tested up to: 7.0.2
    7 Stable tag: 4.16
     7Stable tag: 4.17
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    237237
    238238See all <a href="https://tribulant.com/docs/wordpress-mailing-list-plugin/31/#doc6">releases and full changelogs</a> in our docs.
     239
     240= 4.17 =
     241* SECURITY: Fixed predictable API keys by generating random API keys and rotating existing keys on upgrade. Reported by WPScan.
     242* SECURITY: Fixed CSRF and arbitrary option updates on the API settings page by adding nonce and capability checks and saving only allowed API settings. Reported by WPScan.
     243* SECURITY: Fixed subscriber management access control bypass in subscription and paid subscription links by requiring the authenticated management subscriber session. Reported by Yaswanth Reddy Sunkara.
     244* SECURITY: Prevent subscriber management authentication tokens from being written into page output and set manage-subscription link cookies before page rendering.
     245* SECURITY: Improved the security of subscriber management login tokens.
     246* IMPROVE: Removed PHP null coalescing operators from plugin PHP files for PHP 7.x compatibility.
     247* FIX: Fixed PHP 8+ fatal error in subscription management shortcode when array_merge() received null.
    239248
    240249= 4.16 =
  • newsletters-lite/trunk/views/admin/settings/api.php

    r3190754 r3635791  
    2020       
    2121        <form action="<?php echo esc_url_raw( admin_url('admin.php?page=' . $this -> sections -> settings_api)) ?>" method="post">
     22                <?php wp_nonce_field('newsletters_settings_api'); ?>
    2223                <table class="form-table">
    2324                        <tbody>
    … …  
    3738                                                <th><label for=""><?php esc_html_e('API Endpoint', 'wp-mailinglist'); ?></label></th>
    3839                                                <td>
    39                                                         <code><?php echo $api_endpoint; ?></code>
     40                                                        <code><?php echo esc_html($api_endpoint); ?></code>
    4041                                                        <span class="howto"><?php esc_html_e('The URL to submit API calls to', 'wp-mailinglist'); ?></span>
    4142                                                </td>
  • newsletters-lite/trunk/views/default/management/login-auth.php

    r2582730 r3635791  
    88        <p><a class="newsletters_button" href="<?php echo esc_url_raw($this -> get_managementpost(true)); ?>"><?php esc_html_e('Manage Subscriptions', 'wp-mailinglist'); ?></a></p>
    99       
    10         <script type="text/javascript">jQuery(document).ready(function() { window.location = "<?php echo remove_query_arg(array('method', 'email'), $Html -> retainquery('subscriberauth=' . $subscriberauth)); ?>"; });</script>
     10        <script type="text/javascript">jQuery(document).ready(function() { window.location = "<?php echo esc_js($this -> get_managementpost(true)); ?>"; });</script>
    1111</div>
  • newsletters-lite/trunk/views/default2/management/login-auth.php

    r2582730 r3635791  
    99        <p><a class="newsletters_button btn btn-primary" href="<?php echo esc_url_raw($this -> get_managementpost(true)); ?>"><?php esc_html_e('Manage Subscriptions', 'wp-mailinglist'); ?></a></p>
    1010
    11         <script type="text/javascript">jQuery(document).ready(function() { window.location = "<?php echo remove_query_arg(array('method', 'email'), $Html -> retainquery('subscriberauth=' . $subscriberauth)); ?>"; });</script>
     11        <script type="text/javascript">jQuery(document).ready(function() { window.location = "<?php echo esc_js($this -> get_managementpost(true)); ?>"; });</script>
    1212</div>
  • newsletters-lite/trunk/wp-mailinglist-plugin.php

    r3621582 r3635791  
    99                var $plugin_base;
    1010                var $pre = 'wpml';
    11                 var $version = '4.16';
     11                var $version = '4.17';
    1212                var $dbversion = '1.2.3';
    1313                var $debugging = false;                 //set to "true" to turn on debugging 
    … …  
    270270            return $random_prefix . '-newsletters.log';
    271271        }
     272
     273                function generate_api_key() {
     274                        if (function_exists('wp_generate_password')) {
     275                                return wp_generate_password(64, false, false);
     276                        }
     277
     278                        try {
     279                                if (function_exists('random_bytes')) {
     280                                        return bin2hex(random_bytes(32));
     281                                }
     282                        } catch (Exception $e) {
     283                                // Fall through to OpenSSL below.
     284                        }
     285
     286                        if (function_exists('openssl_random_pseudo_bytes')) {
     287                                $strong = false;
     288                                $bytes = openssl_random_pseudo_bytes(32, $strong);
     289                                if ($bytes !== false && $strong) {
     290                                        return bin2hex($bytes);
     291                                }
     292                        }
     293
     294                        return wp_hash(uniqid('', true) . wp_rand() . microtime(true));
     295                }
    272296
    273297        protected function get_log_htaccess_candidates() {
    … …  
    15741598                    }
    15751599
    1576                         $key = strtoupper(md5(current_time('timestamp')));
     1600                        $key = $this -> generate_api_key();
    15771601                        $this -> update_option('api_key', $key);
    15781602                        echo esc_html($key);
    … …  
    49024926                }
    49034927
     4928                function management_loginauth_redirect() {
     4929                        if (is_admin() || empty($_GET['method']) || $_GET['method'] !== 'loginauth') {
     4930                                return;
     4931                        }
     4932
     4933                        if (empty($_GET['email']) || empty($_GET['subscriberauth'])) {
     4934                                return;
     4935                        }
     4936
     4937                        $managementpost = $this -> get_managementpost();
     4938                        if (!empty($managementpost) && function_exists('get_queried_object_id') && (int) get_queried_object_id() !== (int) $managementpost) {
     4939                                return;
     4940                        }
     4941
     4942                        global $Db, $Subscriber, $Authnews;
     4943
     4944                        $subscriberemailauth = sanitize_text_field(wp_unslash($_GET['email']));
     4945                        $subscriberauth = sanitize_text_field(wp_unslash($_GET['subscriberauth']));
     4946
     4947                        $Db -> model = $Subscriber -> model;
     4948                        if ($subscriber = $Db -> find(array('email' => $subscriberemailauth, 'cookieauth' => $subscriberauth))) {
     4949                                if ($Authnews -> set_cookie($subscriber -> cookieauth) && $Authnews -> set_emailcookie($subscriberemailauth)) {
     4950                                        wp_safe_redirect($this -> get_managementpost(true));
     4951                                        exit();
     4952                                }
     4953                        }
     4954                }
     4955
    49044956                function ajax_managementcustomfields() {
    49054957                       
    … …  
    49865038                                                $_POST = $data = $Field -> validate_optin($_POST, 'management');
    49875039                                                if (!empty($Field -> errors)) {
    4988                                                         $errors = array_merge($errors, $Field -> errors);
     5040                            $errors = array_merge((array) $errors, (array) $Field -> errors);
    49895041                                                }
    49905042
    … …  
    60596111                        switch ($method) {
    60606112                                case 'paidsubscription'                 :
    6061                                         $subscriber_id = sanitize_text_field(wp_unslash($_REQUEST['subscriber_id']));
    6062                                         $list_id = sanitize_text_field(wp_unslash($_REQUEST['list_id']));
    6063                                         $extend = sanitize_text_field(wp_unslash($_REQUEST['extend']));
     6113                                        $subscriber_id = 0;
     6114                                        $list_id = 0;
     6115                                        $extend = '';
     6116
     6117                                        if (isset($_REQUEST['subscriber_id'])) {
     6118                                                $subscriber_id = (int) sanitize_text_field(wp_unslash($_REQUEST['subscriber_id']));
     6119                                        }
     6120
     6121                                        if (isset($_REQUEST['list_id'])) {
     6122                                                $list_id = (int) sanitize_text_field(wp_unslash($_REQUEST['list_id']));
     6123                                        }
     6124
     6125                                        if (isset($_REQUEST['extend'])) {
     6126                                                $extend = sanitize_text_field(wp_unslash($_REQUEST['extend']));
     6127                                        }
    60646128
    60656129                                        if (!empty($subscriber_id)) {
    60666130                                                if (!empty($list_id)) {
    60676131
    6068                                                         $subscriber = $Subscriber -> get($subscriber_id);
    6069                                                         $data = (array) $subscriber;
    6070                                                         $data['list_id'] = $list_id;
    6071                                                         $mailinglist = $Mailinglist -> get($list_id);
    6072                                                         $extend = (empty($extend)) ? false : true;
    6073 
    6074                                                         $Field -> validate_optin($data, 'management');
    6075 
    6076                                                         if (empty($Field -> errors)) {
    6077                                                                 $this -> render('management' . DS . 'paidsubscription', array('subscriber' => $subscriber, 'mailinglist' => $mailinglist, 'extend' => $extend), true, 'default');
     6132                                                        if ($subscriber = $this -> management_authorized_subscriber($subscriber_id)) {
     6133                                                                $data = (array) $subscriber;
     6134                                                                $data['list_id'] = $list_id;
     6135                                                                $mailinglist = $Mailinglist -> get($list_id);
     6136                                                                $extend = (empty($extend)) ? false : true;
     6137
     6138                                                                $Field -> validate_optin($data, 'management');
     6139
     6140                                                                if (empty($Field -> errors)) {
     6141                                                                        $this -> render('management' . DS . 'paidsubscription', array('subscriber' => $subscriber, 'mailinglist' => $mailinglist, 'extend' => $extend), true, 'default');
     6142                                                                } else {
     6143                                                                        $url = $Html -> retainquery('updated=1&error=' . __('Some profile fields are required, please complete them.', 'wp-mailinglist') . '#profile', $this -> get_managementpost(true));
     6144                                                                        $this -> redirect($url);
     6145                                                                }
    60786146                                                        } else {
    6079                                                                 $url = $Html -> retainquery('updated=1&error=' . __('Some profile fields are required, please complete them.', 'wp-mailinglist') . '#profile', $this -> get_managementpost(true));
    6080                                                                 $this -> redirect($url);
     6147                                                                status_header(403);
     6148                                                                $errors[] = __('You are not authorised to manage this subscriber.', 'wp-mailinglist');
    60816149                                                        }
    60826150                                                } else {
    … …  
    60856153                                        } else {
    60866154                                                $errors[] = __('No subscriber was specified', 'wp-mailinglist');
     6155                                        }
     6156
     6157                                        if (!empty($errors)) {
     6158                                                $this -> render('error', array('errors' => $errors), true, 'default');
    60876159                                        }
    60886160
    … …  
    60966168                                        $errors = false;
    60976169                                        $success = false;
    6098                                         $id = (int) sanitize_text_field(wp_unslash($_GET['id']));
     6170                                        $subscriber = false;
     6171                                        $id = 0;
     6172
     6173                                        if (isset($_GET['id'])) {
     6174                                                $id = (int) sanitize_text_field(wp_unslash($_GET['id']));
     6175                                        }
    60996176
    61006177                                        if (!empty($id)) {
    61016178                                                if (!empty($_GET['mailinglists'])) {
    61026179                                                        $Db -> model = $Subscriber -> model;
    6103                                                         if ($subscriber = $Db -> find(array('id' => $id))) {
     6180                                                        if ($subscriber = $this -> management_authorized_subscriber($id)) {
    61046181
    61056182                                                                $subscriber -> mailinglists = explode(",", esc_html($_GET['mailinglists']));
    … …  
    61086185                                                                if ($Subscriber -> optin($subscriber, false, false, false)) {
    61096186                                                                        $success = true;
    6110 
    6111                                                                         $Authnews -> set_emailcookie($subscriber -> email, "+30 days");
    6112                                                                         if (empty($subscriber -> cookieauth) || $subscriber -> cookieauth === md5($subscriber->id)) {
    6113                                                                                 $subscriberauth = $Authnews -> gen_subscriberauth();
    6114                                                                                 $Db -> model = $Subscriber -> model;
    6115                                                                                 $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
    6116                                                                         } else {
    6117                                                                                 $subscriberauth = $subscriber -> cookieauth;
    6118                                                                         }
    6119 
    6120                                                                         $Authnews -> set_cookie($subscriberauth, "+30 days", true);
    61216187                                                                } else {
    61226188                                                                        $errors = $Subscriber -> errors;
    61236189                                                                }
    61246190                                                        } else {
    6125                                                                 $errors[] = __('Subscriber cannot be read', 'wp-mailinglist');
     6191                                                                status_header(403);
     6192                                                                $errors[] = __('You are not authorised to manage this subscriber.', 'wp-mailinglist');
    61266193                                                        }
    61276194                                                } else {
    … …  
    61536220                                                if ($Subscriber -> optin($subscriber, false, false, false)) {
    61546221                                                        $success = true;
    6155 
    6156                                                         $Authnews -> set_emailcookie($subscriber -> email, "+30 days");
    6157                                                         if (empty($subscriber -> cookieauth) || $subscriber -> cookieauth === md5($subscriber->id)) {
    6158                                                                 $subscriberauth = $Authnews -> gen_subscriberauth();
    6159                                                                 $Db -> model = $Subscriber -> model;
    6160                                                                 $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
    6161                                                         } else {
    6162                                                                 $subscriberauth = $subscriber -> cookieauth;
    6163                                                         }
    6164 
    6165                                                         $Authnews -> set_cookie($subscriberauth, "+30 days", true);
    61666222                                                } else {
    61676223                                                        $errors = $Subscriber -> errors;
    … …  
    63976453                                                $subscriberemailauth = $_POST['email'] = $Authnews -> read_emailcookie();
    63986454                                        } else {
    6399                                                 $subscriberemailauth = sanitize_text_field($_GET['email']);
    6400                                         }
    6401 
    6402                                         $subscriberauth = sanitize_text_field($_GET['subscriberauth']);
     6455                                                $subscriberemailauth = sanitize_text_field(wp_unslash($_GET['email']));
     6456                                        }
     6457
     6458                                        $subscriberauth = '';
     6459                                        if (isset($_GET['subscriberauth'])) {
     6460                                                $subscriberauth = sanitize_text_field(wp_unslash($_GET['subscriberauth']));
     6461                                        }
    64036462
    64046463                                        if (!empty($subscriberemailauth)) {
    … …  
    64066465                                                        $Db -> model = $Subscriber -> model;                                                   
    64076466                                                        if ($subscriber = $Db -> find(array('email' => $subscriberemailauth, 'cookieauth' => $subscriberauth))) {
    6408                                                                 global $wpmljavascript;
    6409                                                                 $Authnews -> set_cookie($subscriber -> cookieauth);
    6410                                                                 $Authnews -> set_emailcookie($subscriberemailauth);
     6467                                                                if (!$Authnews -> set_cookie($subscriber -> cookieauth) || !$Authnews -> set_emailcookie($subscriberemailauth)) {
     6468                                                                        $errors[] = __('Authentication failed because the login cookie could not be set. Please try the link again or use the login form.', 'wp-mailinglist');
     6469                                                                }
    64116470                                                        } else {
    64126471                                                                $errors[] = __('Authentication failed, please try again.', 'wp-mailinglist');
    … …  
    64206479
    64216480                                        if (empty($errors)) {
    6422                                                 $this -> render('management' . DS . 'login-auth', array('subscriberauth' => $subscriberauth, 'subscriberemailauth' => $subscriberemailauth), true, 'default');
     6481                                                $this -> render('management' . DS . 'login-auth', false, true, 'default');
    64236482                                        } else {
    64246483                                                $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default');
    … …  
    64266485                                        break;
    64276486                                case 'login'                            :
    6428                                         $errors = array_merge($errors, $newsletters_errors);
     6487                    $errors = array_merge((array) $errors, (array) $newsletters_errors);
    64296488                                        $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default');
    64306489                                        break;
    64316490                                default                                         :
    6432                                         if (!empty($_GET['subscriberauth'])) {
    6433                                                 $_COOKIE['subscriberauth'] = esc_html($_GET['subscriberauth']);
    6434                                         }
    6435 
    64366491                                        if ($subscriber = $Authnews -> logged_in()) {                                                                                           
    64376492                                                if ($this -> get_option('subscriptions') == "Y") {
    … …  
    1288012935
    1288112936
     12937
     12938                if (version_compare($cur_version, "4.17") < 0) {
     12939                    $this -> update_option('api_key', $this -> generate_api_key());
     12940
     12941                    $version = '4.17';
     12942                }
    1288212943
    1288312944                if (version_compare($cur_version, $this->version) < 0) {
    … …  
    1312013181
    1312113182                        // API Stuff
    13122                         // phpcs:ignore
    13123                         $options['api_key'] = strtoupper(md5($_SERVER['SERVER_NAME']));
     13183                        $options['api_key'] = $this -> generate_api_key();
    1312413184
    1312513185                        foreach ($options as $okey => $oval) {
  • newsletters-lite/trunk/wp-mailinglist.php

    r3621582 r3635791  
    44Plugin Name: Newsletters
    55Plugin URI: https://tribulant.com/plugins/view/1/
    6 Version: 4.16
     6Version: 4.17
    77Description: This newsletter software by Tribulant allows users to subscribe to multiple mailing lists on your WordPress website. Send newsletters manually or from posts, manage newsletter templates, view a complete history with tracking, import/export subscribers, accept paid subscriptions and much more. Remove limits by buying PRO. Once purchased, to avoid future issues, remove this version and install and use the paid version in its stead. No data will be lost.
    88Author: Tribulant
    … …  
    59885988                    wp_die( __( 'You do not have permission to do that.', 'wp-mailinglist' ) );
    59895989                }
    5990                 $email_id      = absint( $_GET['email_id']      ?? 0 );
    5991                 $subscriber_id = absint( $_GET['subscriber_id'] ?? 0 );
    5992                 $user_id       = absint( $_GET['user_id']       ?? 0 );
     5990                $email_id = 0;
     5991                $subscriber_id = 0;
     5992                $user_id = 0;
     5993
     5994                if (isset($_GET['email_id'])) {
     5995                    $email_id = absint($_GET['email_id']);
     5996                }
     5997
     5998                if (isset($_GET['subscriber_id'])) {
     5999                    $subscriber_id = absint($_GET['subscriber_id']);
     6000                }
     6001
     6002                if (isset($_GET['user_id'])) {
     6003                    $user_id = absint($_GET['user_id']);
     6004                }
    59936005                check_admin_referer( 'wpml_resend_email_' . $email_id );
    59946006                global $Db, $Email, $Subscriber, $History, $HistoriesAttachment, $Html;
    … …  
    1093410946
    1093510947                if (!empty($_POST)) {
    10936                     $this -> update_option('api_enable', 0);
    10937                     $this -> update_option('api_hosts', 0);
    10938 
    10939                     foreach ($_POST as $pkey => $pval) {
    10940                         $this -> update_option($pkey, $pval);
     10948                    check_admin_referer('newsletters_settings_api');
     10949
     10950                    if (!current_user_can('newsletters_settings_api')) {
     10951                        wp_die(wp_kses_post(__('You do not have permission', 'wp-mailinglist')));
    1094110952                    }
     10953
     10954                    $api_enable = 0;
     10955                    $api_hosts = array();
     10956
     10957                    if (!empty($_POST['api_enable'])) {
     10958                        $api_enable = 1;
     10959                    }
     10960
     10961                    if (!empty($_POST['api_hosts']) && is_array($_POST['api_hosts'])) {
     10962                        $api_hosts = array_filter(array_map('sanitize_text_field', wp_unslash($_POST['api_hosts'])));
     10963                    }
     10964
     10965                    $this -> update_option('api_enable', $api_enable);
     10966                    $this -> update_option('api_hosts', $api_hosts);
    1094210967
    1094310968                    $message = __('API settings have been saved', 'wp-mailinglist');
Note: See TracChangeset for help on using the changeset viewer.