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-webauthn.php +36 -14 6.2.0 → 6.3.0 View file →
@@ -39,8 +39,31 @@
39 39 */
40 40 public const USER_HANDLE_MISMATCH_KEY = 'user_handle_match_failed';
41 41
42 42 /**
43 + * User ID that findOneByCredentialId() lookups are currently scoped to.
44 + * Must be set only via set_expected_user_id() from trusted server-side
45 + * context (e.g. the WP_User passed down the 2FA login chain) — never
46 + * derived from request input inside this class.
47 + *
48 + * @var int|null
49 + */
50 + private $expected_user_id = null;
51 +
52 + /**
53 + * Restrict findOneByCredentialId() to a specific user's credential set.
54 + * Call this before delegating to Webauthn\Server so the library's internal
55 + * repository lookups stay scoped to the expected 2FA target user.
56 + *
57 + * @param int|null $user_id Trusted user ID, or null to clear the scope.
58 + *
59 + * @return void
60 + */
61 + public function set_expected_user_id( ?int $user_id ): void {
62 + $this->expected_user_id = $user_id;
63 + }
64 +
65 + /**
43 66 * Get user credentials.
44 67 *
45 68 * @param int $user_id The user ID.
46 69 *
@@ -63,8 +86,12 @@
63 86 }
64 87
65 88 /**
66 89 * Get one credential by credential ID.
90 + * {@inheritDoc}
91 + * Interface-mandated single-parameter signature. Scoping to a specific
92 + * user is done via $this->expected_user_id, set beforehand through
93 + * set_expected_user_id() by trusted calling code — never via $_POST.
67 94 *
68 95 * @param string $public_key_credential_id The public key credential ID.
69 96 *
70 97 * @return PublicKeyCredentialSource|null
@@ -69,23 +96,18 @@
69 96 *
70 97 * @return PublicKeyCredentialSource|null
71 98 */
72 99 public function findOneByCredentialId( string $public_key_credential_id ): ?PublicKeyCredentialSource {
73 - $username = defender_get_data_from_request( 'username', 'p' );
74 - if ( isset( $username ) ) {
75 - $user = get_user_by( 'login', $username );
100 + if ( null === $this->expected_user_id ) {
101 + // No trusted scope set — deny rather than search globally.
102 + // Never needs an unscoped, cross-account lookup.
103 + return null;
104 + }
76 105
77 - if ( is_object( $user ) ) {
78 - $user_id = $user->ID;
79 - } else {
80 - $user_id = 0;
81 - }
82 - } else {
83 - $user_id = get_current_user_id();
84 - }
85 - $data = $this->getCredentials( $user_id );
86 - if ( isset( $data[ base64_encode( $public_key_credential_id ) ]['credential_source'] ) ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
87 - $credential_source = $data[ base64_encode( $public_key_credential_id ) ]['credential_source']; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
106 + $data = $this->getCredentials( $this->expected_user_id );
107 + $key = base64_encode( $public_key_credential_id ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
108 + if ( isset( $data[ $key ]['credential_source'] ) ) {
109 + $credential_source = $data[ $key ]['credential_source']; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
88 110
89 111 return PublicKeyCredentialSource::createFromArray( $this->normalize_legacy_trust_path( $credential_source ) );
90 112 }
91 113