Changeset 3635791
- Timestamp:
- 08/05/2026 08:00:53 PM (3 months ago)
- Location:
- newsletters-lite/trunk
- Files:
-
- 9 edited
-
helpers/auth.php (modified) (4 diffs)
-
includes/checkinit.php (modified) (1 diff)
-
models/subscriber.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
-
views/admin/settings/api.php (modified) (2 diffs)
-
views/default/management/login-auth.php (modified) (1 diff)
-
views/default2/management/login-auth.php (modified) (1 diff)
-
wp-mailinglist-plugin.php (modified) (16 diffs)
-
wp-mailinglist.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
newsletters-lite/trunk/helpers/auth.php
r3621582 r3635791 141 141 break; 142 142 } 143 144 return true; 143 145 } 144 146 … … 163 165 setcookie($this -> cookiename, $value, strtotime($days), '/'); 164 166 } else { 165 $this -> javascript_cookie($this -> cookiename, $value);167 return false; 166 168 } 167 169 … … 180 182 setcookie($this -> cookiename, $value, strtotime($days), '/'); 181 183 } else { 182 $this -> javascript_cookie($this -> cookiename, $value); 184 $_SESSION[$this -> cookiename] = $value; 185 return false; 183 186 } 184 187 … … 228 231 229 232 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)); 232 254 } 233 255 } -
newsletters-lite/trunk/includes/checkinit.php
r3566485 r3635791 56 56 $this -> add_action('widgets_init', 'widget_register', 10, 1); 57 57 $this -> add_action('wp_head', 'wp_head', 15, 1); 58 $this -> add_action('template_redirect', 'management_loginauth_redirect', 0, 1); 58 59 $this -> add_action('wp_footer'); 59 60 $this -> add_action('admin_footer'); -
newsletters-lite/trunk/models/subscriber.php
r3303758 r3635791 816 816 817 817 $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() ); 819 820 820 821 if ( ! $result->success ) { -
newsletters-lite/trunk/readme.txt
r3621582 r3635791 5 5 Requires at least: 3.8 6 6 Tested up to: 7.0.2 7 Stable tag: 4.1 67 Stable tag: 4.17 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 237 237 238 238 See 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. 239 248 240 249 = 4.16 = -
newsletters-lite/trunk/views/admin/settings/api.php
r3190754 r3635791 20 20 21 21 <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'); ?> 22 23 <table class="form-table"> 23 24 <tbody> … … 37 38 <th><label for=""><?php esc_html_e('API Endpoint', 'wp-mailinglist'); ?></label></th> 38 39 <td> 39 <code><?php echo $api_endpoint; ?></code>40 <code><?php echo esc_html($api_endpoint); ?></code> 40 41 <span class="howto"><?php esc_html_e('The URL to submit API calls to', 'wp-mailinglist'); ?></span> 41 42 </td> -
newsletters-lite/trunk/views/default/management/login-auth.php
r2582730 r3635791 8 8 <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> 9 9 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> 11 11 </div> -
newsletters-lite/trunk/views/default2/management/login-auth.php
r2582730 r3635791 9 9 <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> 10 10 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> 12 12 </div> -
newsletters-lite/trunk/wp-mailinglist-plugin.php
r3621582 r3635791 9 9 var $plugin_base; 10 10 var $pre = 'wpml'; 11 var $version = '4.1 6';11 var $version = '4.17'; 12 12 var $dbversion = '1.2.3'; 13 13 var $debugging = false; //set to "true" to turn on debugging … … 270 270 return $random_prefix . '-newsletters.log'; 271 271 } 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 } 272 296 273 297 protected function get_log_htaccess_candidates() { … … 1574 1598 } 1575 1599 1576 $key = strtoupper(md5(current_time('timestamp')));1600 $key = $this -> generate_api_key(); 1577 1601 $this -> update_option('api_key', $key); 1578 1602 echo esc_html($key); … … 4902 4926 } 4903 4927 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 4904 4956 function ajax_managementcustomfields() { 4905 4957 … … 4986 5038 $_POST = $data = $Field -> validate_optin($_POST, 'management'); 4987 5039 if (!empty($Field -> errors)) { 4988 $errors = array_merge($errors,$Field -> errors);5040 $errors = array_merge((array) $errors, (array) $Field -> errors); 4989 5041 } 4990 5042 … … 6059 6111 switch ($method) { 6060 6112 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 } 6064 6128 6065 6129 if (!empty($subscriber_id)) { 6066 6130 if (!empty($list_id)) { 6067 6131 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 } 6078 6146 } 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'); 6081 6149 } 6082 6150 } else { … … 6085 6153 } else { 6086 6154 $errors[] = __('No subscriber was specified', 'wp-mailinglist'); 6155 } 6156 6157 if (!empty($errors)) { 6158 $this -> render('error', array('errors' => $errors), true, 'default'); 6087 6159 } 6088 6160 … … 6096 6168 $errors = false; 6097 6169 $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 } 6099 6176 6100 6177 if (!empty($id)) { 6101 6178 if (!empty($_GET['mailinglists'])) { 6102 6179 $Db -> model = $Subscriber -> model; 6103 if ($subscriber = $ Db -> find(array('id' => $id))) {6180 if ($subscriber = $this -> management_authorized_subscriber($id)) { 6104 6181 6105 6182 $subscriber -> mailinglists = explode(",", esc_html($_GET['mailinglists'])); … … 6108 6185 if ($Subscriber -> optin($subscriber, false, false, false)) { 6109 6186 $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);6121 6187 } else { 6122 6188 $errors = $Subscriber -> errors; 6123 6189 } 6124 6190 } 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'); 6126 6193 } 6127 6194 } else { … … 6153 6220 if ($Subscriber -> optin($subscriber, false, false, false)) { 6154 6221 $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);6166 6222 } else { 6167 6223 $errors = $Subscriber -> errors; … … 6397 6453 $subscriberemailauth = $_POST['email'] = $Authnews -> read_emailcookie(); 6398 6454 } 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 } 6403 6462 6404 6463 if (!empty($subscriberemailauth)) { … … 6406 6465 $Db -> model = $Subscriber -> model; 6407 6466 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 } 6411 6470 } else { 6412 6471 $errors[] = __('Authentication failed, please try again.', 'wp-mailinglist'); … … 6420 6479 6421 6480 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'); 6423 6482 } else { 6424 6483 $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default'); … … 6426 6485 break; 6427 6486 case 'login' : 6428 $errors = array_merge($errors,$newsletters_errors);6487 $errors = array_merge((array) $errors, (array) $newsletters_errors); 6429 6488 $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default'); 6430 6489 break; 6431 6490 default : 6432 if (!empty($_GET['subscriberauth'])) {6433 $_COOKIE['subscriberauth'] = esc_html($_GET['subscriberauth']);6434 }6435 6436 6491 if ($subscriber = $Authnews -> logged_in()) { 6437 6492 if ($this -> get_option('subscriptions') == "Y") { … … 12880 12935 12881 12936 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 } 12882 12943 12883 12944 if (version_compare($cur_version, $this->version) < 0) { … … 13120 13181 13121 13182 // API Stuff 13122 // phpcs:ignore 13123 $options['api_key'] = strtoupper(md5($_SERVER['SERVER_NAME'])); 13183 $options['api_key'] = $this -> generate_api_key(); 13124 13184 13125 13185 foreach ($options as $okey => $oval) { -
newsletters-lite/trunk/wp-mailinglist.php
r3621582 r3635791 4 4 Plugin Name: Newsletters 5 5 Plugin URI: https://tribulant.com/plugins/view/1/ 6 Version: 4.1 66 Version: 4.17 7 7 Description: 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. 8 8 Author: Tribulant … … 5988 5988 wp_die( __( 'You do not have permission to do that.', 'wp-mailinglist' ) ); 5989 5989 } 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 } 5993 6005 check_admin_referer( 'wpml_resend_email_' . $email_id ); 5994 6006 global $Db, $Email, $Subscriber, $History, $HistoriesAttachment, $Html; … … 10934 10946 10935 10947 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'))); 10941 10952 } 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); 10942 10967 10943 10968 $message = __('API settings have been saved', 'wp-mailinglist');
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)