PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
← All changes | src/component/class-firewall.php +40 -5 6.2.3 → 6.3.0 View file →
@@ -14,9 +14,9 @@
14 14 use WP_Defender\Model\Lockout_Ip;
15 15 use WP_Defender\Behavior\WPMUDEV;
16 16 use WP_Defender\Model\Lockout_Log;
17 17 use WP_Defender\Model\Onboard;
18 -use MaxMind\Db\Reader\InvalidDatabaseException;
18 +use WP_DEFENDER_VENDOR\MaxMind\Db\Reader\InvalidDatabaseException;
19 19 use WP_Defender\Model\Setting\Firewall as Model_Firewall;
20 20 use WP_Defender\Component\Trusted_Proxy_Preset\Cloudflare_Proxy;
21 21 use WP_Defender\Component\Trusted_Proxy_Preset\Trusted_Proxy_Preset;
22 22 use WP_Defender\Controller\Firewall as Firewall_Controller;
@@ -69,12 +69,44 @@
69 69
70 70 /**
71 71 * Check is the access from authenticated staff.
72 72 *
73 - * @return bool
73 + * Validates the `wpmudev_is_staff` cookie token by verifying:
74 + * - Token version and structure (v1.<payload>.<signature>)
75 + * - HMAC-SHA256 signature against site salt (`wpmudev_remote_access`)
76 + * - Token expiration timestamp against current time
77 + * - Audience (`aud`) against current site URL (`home_url('/')`)
78 + * - Subject (`sub`) against currently authenticated user ID
79 + *
80 + * @return bool True if staff access token is valid and unexpired, false otherwise.
74 81 */
75 82 private function is_authenticated_staff_access(): bool {
76 - return '1' === defender_get_data_from_request( 'wpmudev_is_staff', 'c' );
83 + $cookie = defender_get_data_from_request( 'wpmudev_is_staff', 'c' );
84 + if ( ! is_string( $cookie ) ) {
85 + return false;
86 + }
87 +
88 + $token = explode( '.', $cookie, 3 );
89 + if ( 3 !== count( $token ) || 'v1' !== $token[0] ) {
90 + return false;
91 + }
92 +
93 + $signature = hash_hmac( 'sha256', $token[1], wp_salt( 'wpmudev_remote_access' ) );
94 + if ( ! hash_equals( $signature, $token[2] ) ) {
95 + return false;
96 + }
97 + // Improve flow to avoid bypassing staff access authentication via an unsigned cookie. Use legitim payload.
98 + $payload = base64_decode( strtr( $token[1], '-_', '+/' ) . str_repeat( '=', ( 4 - strlen( $token[1] ) % 4 ) % 4 ), true );// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
99 + $payload = is_string( $payload ) ? json_decode( $payload, true ) : null;
100 +
101 + return is_array( $payload ) &&
102 + isset( $payload['aud'], $payload['exp'], $payload['sub'] ) &&
103 + is_string( $payload['aud'] ) &&
104 + is_numeric( $payload['exp'] ) &&
105 + is_numeric( $payload['sub'] ) &&
106 + (int) $payload['exp'] > time() &&
107 + hash_equals( home_url( '/' ), $payload['aud'] ) &&
108 + get_current_user_id() === (int) $payload['sub'];
77 109 }
78 110
79 111 /**
80 112 * Check if the access is from our staff access.
@@ -96,10 +128,13 @@
96 128 $is_remote_access = is_object( WPMUDEV_Dashboard::$api ) &&
97 129 true === WPMUDEV_Dashboard::$api->remote_access_details( 'enabled' );
98 130
99 131 if ( $is_remote_access ) {
100 - $access = $wpmu_dev->get_remote_access();
101 - if ( $this->is_authenticated_staff_access() || $this->is_commencing_staff_access( $access ) ) {
132 + $access = $wpmu_dev->get_remote_access();
133 + $is_authenticated_staff_access = isset( $access['userid'] ) &&
134 + get_current_user_id() === (int) $access['userid'] &&
135 + $this->is_authenticated_staff_access();
136 + if ( $is_authenticated_staff_access || $this->is_commencing_staff_access( $access ) ) {
102 137 $this->log( $access, Firewall_Controller::FIREWALL_LOG );
103 138
104 139 return true;
105 140 }