Affected plugin | SiteGround Security |
Active installs | 600,000+ |
Vulnerable version | <= 1.3.0 |
Audited version | 1.3.0 |
Fully patched version | 1.3.2 (Not verified by Snicco) |
Recommended remediation | Upgrade to version 1.3.2 or higher. |
Description
The plugin uses string comparison operators that don’t mitigate time-based attacks in several places where secrets are compared to user input.
A skilled attacker, given enough requests, can abuse this to reverse secrets using time-based-side-channel attacks.
Proof of concept
Validation of 2FA challenge tokens:
(Fixed in 1.3.2)
public function get_2fa_nonce_cookie() {
// Bail if the cookie doens't exists.
if ( empty( $_COOKIE['sgs_2fa_login_nonce'] ) ) {
return;
}
// Parse the cookie.
$cookie_data = explode( '|', $_COOKIE['sgs_2fa_login_nonce'] );
// Get the user nonce meta.
$meta_nonce = get_user_meta( $cookie_data[0], 'sgs_2fa_login_nonce', true );
if ( empty( $meta_nonce ) || empty( $cookie_data[0] ) ) {
return;
}
// Bail if the nonce is invalid.
if ( $meta_nonce !== $cookie_data[1] ) { // phpcs:ignore
return;
}
// Return the cookie data.
return $cookie_data;
}
Validation of emergency codes:
(Fixed in 1.3.2)
public function validate_backup_login( $code, $user ) {
$codes = get_user_meta( $user, 'sg_security_2fa_backup_codes', true ); // phpcs:ignore
// Bail if the user doesn't have backup codes.
if ( empty( $codes ) ) {
return false;
}
$key = array_search( $code, $codes );
// Bail if the code doesn't exists in the user backup codes.
if ( false === $key ) {
return false;
}
// Remove the used key.
unset( $codes[ $key ] );
// Add additional backup codes to the user meta, if the user has used 4 or more backup codes.
$this->maybe_add_additional_backup_codes( $codes, $user );
return true;
}
Validation of “remember 2FA check” cookie:
public function check_2fa_cookie( $user_login, $user ) {
// 2FA user cookie name.
$sg_2fa_user_cookie = 'sg_security_2fa_dnc_cookie';
// Bail if the cookie doens't exists.
if ( ! isset( $_COOKIE[ $sg_2fa_user_cookie ] ) ) {
return false;
}
// Parse the cookie.
$cookie_data = explode( '|', $_COOKIE[ $sg_2fa_user_cookie ] );
if (
// If the 2FA is configured for the user.
1 == get_user_meta( $cookie_data[0], 'sg_security_2fa_configured', true ) && // phpcs:ignore
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.
) {
return true;
}
return false;
}
Timeline
Vendor contacted | September 07, 2022 |
First Response | September 12, 2022 |
Fully patched at | September 21, 2022 (Not verified by Snicco) |
Publicly disclosed | April 24, 2023 |
Leave a Reply