PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.4
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.4
3.5.4 3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
← All changes | includes/frontend/class-wpsc-shortcode-three.php +34 -5 3.3.9 → 3.5.4 View file →
@@ -52,9 +52,9 @@
52 52 }
53 53
54 54 if ( $ticket_id && $auth_code ) {
55 55 $ticket = new WPSC_Ticket( $ticket_id );
56 - self::$url_auth = $ticket->auth_code == $auth_code ? true : false;
56 + self::$url_auth = ( $ticket->auth_code && hash_equals( (string) $ticket->auth_code, $auth_code ) );
57 57 }
58 58 }
59 59
60 60 ob_start();?>
@@ -208,9 +208,9 @@
208 208 /* translators: %1$s: customer name */
209 209 printf( esc_attr__( 'Logged-in as %1$s', 'supportcandy' ), '<strong>' . esc_attr( $current_user->customer->name ) . '</strong>' );
210 210 ?>
211 211 </span>
212 - <a class="wpsc-link" href="javascript:wpsc_user_logout(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_user_logout' ) ); ?>');"><?php esc_attr_e( 'Log out', 'supportcandy' ); ?></a>
212 + <span class="wpsc-link" onclick="wpsc_user_logout(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_user_logout' ) ); ?>');"><?php esc_attr_e( 'Log out', 'supportcandy' ); ?></span>
213 213 </div>
214 214 <?php
215 215 endif
216 216 ?>
@@ -275,9 +275,9 @@
275 275 */
276 276 public static function get_authenticate_open_ticket() {
277 277
278 278 if ( check_ajax_referer( 'wpsc_authenticate_open_ticket', '_ajax_nonce', false ) != 1 ) {
279 - wp_send_json_error( 'Unauthorised request!', 401 );
279 + wp_send_json_error( 'Unauthorized request!', 401 );
280 280 }
281 281
282 282 $ticket_id = isset( $_POST['ticket_id'] ) ? intval( $_POST['ticket_id'] ) : 0;
283 283 $email_address = isset( $_POST['email_address'] ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
@@ -336,9 +336,9 @@
336 336 ?>
337 337
338 338 <div class="auth-inner-container">
339 339 <h2><?php esc_attr_e( 'Open existing ticket', 'supportcandy' ); ?></h2>
340 - <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a 6-digit one-time pass code to the email address you provided. Please insert it below and submit to open ticket!', 'supportcandy' ); ?></small>
340 + <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address. Please insert it below and submit to open ticket!', 'supportcandy' ); ?></small>
341 341 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-open-ticket-auth">
342 342 <input type="text" name="otp" autocomplete="off"/>
343 343 <button class="wpsc-button normal primary" onclick="wpsc_confirm_open_ticket_auth(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_open_ticket_auth' ) ); ?>')"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
344 344 <input type="hidden" name="action" value="wpsc_confirm_open_ticket_auth"/>
@@ -389,10 +389,20 @@
389 389 * @return void
390 390 */
391 391 public static function confirm_open_ticket_auth() {
392 392
393 + // Rate limiting (mirrors WPSC_Current_User::confirm_guest_login()).
394 + $ip_address = WPSC_DF_IP_Address::get_current_user_ip();
395 + $attempt_key = 'wpsc_otp_attempts_' . md5( $ip_address );
396 + $attempts = get_transient( $attempt_key );
397 + $attempts = $attempts ? $attempts : 1;
398 +
399 + if ( $attempts >= 5 ) {
400 + wp_send_json_error( 'Too many attempts. Please try again later.', 429 );
401 + }
402 +
393 403 if ( check_ajax_referer( 'wpsc_confirm_open_ticket_auth', '_ajax_nonce', false ) != 1 ) {
394 - wp_send_json_error( 'Unauthorised request!', 401 );
404 + wp_send_json_error( 'Unauthorized request!', 401 );
395 405 }
396 406
397 407 $page_settings = get_option( 'wpsc-gs-page-settings' );
398 408
@@ -411,11 +421,30 @@
411 421 wp_send_json_error( 'Bad request', 400 );
412 422 }
413 423
414 424 if ( ! $otp->is_valid( $verification_otp ) ) {
425 +
426 + // Increment attempt counter.
427 + ++$attempts;
428 + set_transient( $attempt_key, $attempts, 300 ); // 5 minute lockout.
429 +
430 + // Add per-OTP attempt tracking.
431 + $otp_attempt_key = 'wpsc_otp_' . $id . '_attempts';
432 + $otp_attempts = get_transient( $otp_attempt_key );
433 + $otp_attempts = $otp_attempts ? $otp_attempts + 1 : 1;
434 + set_transient( $otp_attempt_key, $otp_attempts, 600 );
435 +
436 + if ( $otp_attempts >= 3 ) {
437 + WPSC_Email_OTP::destroy( $otp );
438 + wp_send_json_error( 'OTP has been invalidated due to too many failed attempts', 403 );
439 + }
440 +
415 441 echo wp_json_encode( array( 'isSuccess' => 0 ) );
416 442 wp_die();
417 443 }
444 +
445 + // Clear rate limiting on success.
446 + delete_transient( $attempt_key );
418 447
419 448 $data = json_decode( $otp->data, true );
420 449 $data['auth_token'] = WPSC_Functions::get_random_string( 100 );
421 450 $data['auth_type'] = 'open-ticket';