۱. مقدمه
مرورگرهای مدرن فقط نمایشدهنده صفحات HTML نیستند؛ آنها مجموعهای پیچیده از تجزیهکنندهها (Parser)، رمزگشاها (Decoder)، سندباکس (Sandbox)، کامپایلرهای JIT، رابطهای برنامهنویسی کاربردی سیستمعامل (API) و مسیرهای شبکهای هستند که مرورگر تمامی آنها را باید بهصورت همزمان اجرا و مدیریت میکنند. همین پیچیدگی باعث میشود مرورگرها یکی از مهمترین و حساسترین اهداف در حوزه امنیت نرمافزار باشند و خطاهای کوچک در اعتبارسنجی ورودی، بهویژه در مسیرهای پردازش دادههای رسانهای (Media) بتوانند به آسیبپذیریهای جدی حافظهای تبدیل شوند.
کاربر ممکن است تنها یک صفحه وب، تماس ویدیویی، فایل رسانهای یا برنامه تحت وب را باز میکند؛ اما در پشت صحنه، مرورگر باید دادههایی را پردازش کند که معمولاً از منابع غیرقابل اعتماد میآیند. این دادهها میتوانند شامل کد JavaScript، ساختارهای HTML و CSS، تصاویر، فونتها، ویدیوها، بستههای شبکه، جریانهای صوتی و تصویری و حتی دادههای رسانهای بلادرنگ (real-time) باشند. هرکدام از این مسیرها اگر بهدرستی اعتبارسنجی نشوند، میتوانند به نقطه ورود مهاجم تبدیل شوند.
آسیبپذیری CVE-2026-2757 دقیقاً در همین دسته قرار میگیرد؛ این یک خطای شرط مرزی (Boundary Condition) در مسیر پردازش دادههای صوتی/تصویری (Audio/Video) مربوط به WebRTC در فایرفاکس است که در نهایت میتواند به تخریب حافظه (Memory Corruption) منجر شود. موزیلا این آسیبپذیری را در فایرفاکس 148 و نسخههای ESR (Extended Support Release) مربوطه برطرف کرده و NVD نیز آن را با امتیاز CVSS 9.8 و شدت بحرانی ثبت کرده است.
۱.۱ چرا آسیبپذیریهای مرورگر اهمیت دارند؟
اهمیت آسیبپذیریهای مرورگر از اینجا ناشی میشود که مرورگر دقیقاً در مرز میان اینترنت و سیستم کاربر قرار دارد. یک تخریب حافظه لزوماً به معنای اجرای کد از راه دور قطعی (RCE) نیست، اما میتواند نقطه شروع توانمندیهای پایه (Primitive) مهاجم مانند به دست آوردن توانمندی پایه خواندن حافظه خارج از مرز (Out-of-Bounds Read)، توانمندی پایه نوشتن خارج از مرز (Out-of-Bounds Write
)، توانمندی پایه نشت اطلاعات (Information Leak) یا توانمندی پایه زنجیرهسازی مراحل بهرهبرداری (Exploit) جدیتر باشد.
به همین دلیل، عرضهکنندگان (Vendor) بزرگی مانند موزیلا، آسیبپذیریهای ایمنی حافظه (Memory Safety) را بسیار جدی میگیرند. حتی در اطلاعیههای امنیتی رسمی (Advisory) موزیلا معمولاً اشاره میشود که برخی از خطاهای ایمنی حافظه شواهدی از تخریب حافظه دارند و با تلاش کافی ممکن است برای اجرای کد مورد سوءاستفاده قرار گیرند.
آسیبپذیری CVE-2026-2757 نیز از همین منظر اهمیت دارد. این آسیبپذیری صرفاً یک کرش ساده در یک بخش کماهمیت نیست؛ بلکه در یکی از مسیرهای پردازش دادههای رسانهای در فایرفاکس قرار دارد، جایی که دادههای ورودی میتوانند از سمت یک همتا (Peer) خارجی و در قالب جریان صوتی/تصویری (Audio/Video Stream) وارد مرورگر شوند.
۱.۲ چرا WebRTC یک Attack Surface حساس است؟
پروتکل WebRTC (ارتباط واقعیزمان وب (Web Real-Time Communication)) قابلیتی است که به برنامههای وب اجازه میدهد ارتباطات صوتی، تصویری و دادهای زمان واقعی (real-time) برقرار کنند. طبق توضیحات MDN (شبکه توسعهدهندگان موزیلا)، WebRTC به وبسایتها و برنامههای وب امکان میدهد جریانهای صوتی/تصویری و همچنین دادههای دلخواه (Arbitrary data) را بین مرورگرها منتقل کنند، بدون اینکه نیازی به نصب پلاگین یا نرمافزار جانبی باشد.
همین ویژگی باعث میشود WebRTC از نظر امنیتی بسیار حساس باشد. برخلاف بسیاری از قابلیتهای سنتی وب که عمدتاً بر پایه مدل درخواست (Request)/پاسخ (Response) کار میکنند، WebRTC با جریانهای زمان واقعی، مذاکره (شناخت شیوه پردازش و فرمت مدیا) کدک (Codec negotiation)، پردازش بستهها (packet processing)، رمزگشایی رسانه (media decoding) و ارتباطات همتا به همتا (peer-to-peer) سروکار دارد. این یعنی مرورگر باید دادههایی را پردازش کند که هم پیچیده هستند، هم بهصورت پیوسته وارد میشوند و در بسیاری از سناریوها، تحت کنترل مستقیم یا غیرمستقیم طرف مقابل قرار دارند.
در یک سناریوی ساده، کاربر ممکن است وارد یک تماس ویدیویی شود یا از یک وباپلیکیشن مبتنی بر WebRTC استفاده کند. در این حالت، مرورگر باید جریان دریافتی را دریافت، رمزگشایی، درک و نمایش بدهد (اصطلاحا render باید کند). اگر در هر مرحله از این خط پردازش (pipeline)، بهویژه در بخش تحلیل فرمت کدک یا رمزگشا، فرضی نادرست درباره اندازه، ساختار یا اعتبار داده وجود داشته باشد، همان فرض اشتباه میتواند به یک آسیبپذیری حافظهای تبدیل شود.
در مورد CVE-2026-2757، مسیر آسیبپذیر مربوط به رمزگشایی دادههای فشرده شده با استاندارد H.264 یا MPEG-4 Part 10 در WebRTC مرورگر Firefox است؛ یعنی جایی که دادههای ویدیویی H.264 از مسیر WebRTC وارد مرورگر میشود و در شرایط خاص به مسیر رمزگشای Gecko Media Plugin (یا همان GMP) میرسد.
۱.۳ نقش رمزگشاهای دادههای رسانهای (Media Data Decoders) در امنیت مرورگر
رمزگشاهای دادههای رسانهای وظیفه دارند دادههای فشردهشده صوتی یا تصویری را به فرم قابل پخش تبدیل کنند. برای مثال، زمانی که یک جریان ویدیویی با کدکهایی مانند H.264 ارسال میشود، مرورگر باید آن جریان را رمزگشایی کند تا بتواند تصویر نهایی را نمایش دهد. این فرآیند به ظاهر ساده است، اما از نظر امنیتی یکی از خطرناکترین بخشهای مرورگر محسوب میشود.
دلیل اصلی این خطر، پیچیدگی ذاتی فرمتهای رسانهای است. کدکها معمولاً دارای ساختارهای داخلی پیچیده، هدرهای متغیر (variable headers)، بافرهای متعدد، اندازههای وابسته به ورودی و عملیات سطح پایین روی حافظه هستند. بسیاری از این اجزا به زبانهایی مانند C یا C++ نوشته شدهاند؛ زبانهایی که خطاهایی نظیر سرریز بافر (buffer overflow)، سرریز عدد صحیح (integer overflow)، کمبود عدد صحیح (integer underflow)، استفاده پس از آزادسازی (use-after-free) و دسترسی خارج از محدوده (out-of-bounds access) در آنها همچنان ممکن است رخ دهد.
در مرورگر Firefox، پردازش H.264 بسته به شرایط از مسیرهای مختلفی عبور میکند. Firefox برای رمزگشایی ویدیوهایی مانند H.264، چندین بکاند (backend) مختلف دارد و در برخی شرایط، مسیر جایگزین (fallback path
) رمزگشایی را از طریق افزونههای Gecko Media Plugin (یا به اختصار GMP) انجام میدهد؛ مسیری که از نظر تاریخی برای کامپوننتهایی مانند OpenH264 مورد استفاده قرار گرفته است.
کتابخانه OpenH264 نیز در Firefox برای پشتیبانی از WebRTC و ارتباطات ویدیویی به کار میرود. شایان ذکر است، این کتابخانه متن باز و توسط Cisco برای پشتیبانی از جریانهای رسانهای مبتنی بر H264 توسعه داده شده است. مرورگر Firefox همراه با افزونه OpenH264 عرضه میشود تا قابلیت پشتیبانی از WebRTC و ارتباطات ویدیویی را فراهم کند.
در نتیجه، امنیت رمزگشاهای دادههای رسانهای موضوعی حاشیهای نیست. اگر رمزگشا دادهای را بر اساس فرضی نادرست پردازش کند، مهاجم ممکن است با ارسال یک فریم غیرعادی (malformed frame)، رفتار حافظه برنامه را از مسیر عادی خارج کند. CVE-2026-2757 نمونهای از همین مسئله است؛ ورودی بسیار کوتاه (یعنی تصاویر رمزگذاری شده با اندازه 1 تا 3 بایت) باعث میشود کد آسیبپذیر در مسیر GMP مربوط به H.264، با فرض اشتباه درباره اندازه بافر عمل کند و به خواندن/نوشتن خارج از محدوده (out-of-bounds read/write) منجر شود.
۱.۴ معرفی کوتاه CVE-2026-2757
CVE-2026-2757 یک آسیبپذیری از نوع پردازش نادرست شرایط مرزی (Incorrect Boundary Conditions) در مولفه WebRTC: Audio/Video مرورگر Firefox است. این آسیبپذیری طبق NVD (پایگاه داده ملی آسیبپذیریها) بر روی نسخههای Firefox قبل از 148، و Firefox ESR قبل از 115.23 و 140.8 و همچنین Thunderbird نسخههای قبل از 148 و 140.8 تأثیر میگذارد. نسخههای رفعشده شامل Firefox 148، Firefox ESR 115.33، Firefox ESR 140.8، Thunderbird 148 و Thunderbird 140.8 هستند.
این آسیبپذیری در مسیر رمزگشایی H.264 مربوط به WebRTC، هنگام استفاده از Gecko Media Plugin یا به اختصار GMP Decoder کشف شده است. تابع WebrtcGmpVideoDecoder::Decode_g میتوانست با بافرهای بسیار کوچک از نوع EncodedImage (با اندازه ۱ تا ۳ بایت) فراخوانی شود. مشکل از آنجا آغاز میشود که کد، یک هدر چهار بایتی را داخل بافر مینویسد، در حالی که بافر ممکن است کمتر از چهار بایت فضا داشته باشد. این مسئله باعث نوشتن خارج از محدوده تخصیصیافته (out-of-bounds write) میشود. سپس محاسبه size – 4 نیز میتواند منجر به کمبود عدد صحیح (integer underflow) شود و عملیات کپی را به یک خواندن/نوشتن خارج از محدوده بزرگ (out-of-bounds read/write) تبدیل کند.
این آسیبپذیری از نظر شدت نیز بسیار قابل توجه است. NVD برای CVE-2026-2757 امتیاز CVSS 3.1 برابر ۹.۸ با شدت Critical ثبت کرده است. بردار CVSS نیز به صورت AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H است؛ یعنی از نظر CVSS، این آسیبپذیری دارای حمله از راه دور شبکهای، پیچیدگی حمله پایین، بدون نیاز به دسترسی قبلی، بدون نیاز به تعامل کاربر و با تأثیر بالا بر محرمانگی، صحت و دسترسپذیری با شدت بالا ارزیابی شده است.
۱.۵ خلاصه تأثیر آسیبپذیری
تأثیر اصلی CVE-2026-2757 از این واقعیت ناشی میشود که مهاجم میتواند از طریق دادههای کنترلشده در مسیر WebRTC H.264، وضعیت حافظه را در مسیر رمزگشای GMP مختل کند. این آسیبپذیری یک primitive خواندن/نوشتن خارج از محدوده تحت کنترل مهاجم ایجاد میکند که در فرآیند GMP رخ میدهد. در سطح عملی، پیامدهای احتمالی این آسیبپذیری را میتوان در چند دسته خلاصه کرد:
- کرش یا عدم سرویسدهی | اجرای مرورگر: سادهترین نتیجه تخریب حافظه این است که پروسه آسیبپذیر مرورگر کرش کند. اگر این کرش در فرآیند GMP رخ دهد، ممکن است کل مرورگر بلافاصله از کار نیفتد، اما تجربه کاربر، تماس WebRTC یا پردازش رسانه به طور قابل توجهی مختل خواهد شد و دچار عدم سرویسدهی میشود.
- خواندن خارج از محدوده (Out-of-Bounds Read): اگر مهاجم بتواند از این توانمندی پایه (Primitive) برای خواندن خارج از محدوده استفاده کند، ممکن است به دادههایی دسترسی یابد که نباید در اختیار او باشند. چنین توانمندیهای پایهای در زنجیره بهرهبرداری معمولاً برای نشت اطلاعات یا دور زدن دفاعهایی مانند ASLR ارزشمند هستند.
- نوشتن خارج از محدوده و تخریب هیپ (Out-of-Bounds Write and Heap Corruption): این بخش خطرناکتر است، زیرا توانمندی پایه نوشتن خارج از محدوده میتواند ساختارهای حافظه را تغییر دهد و در شرایط مناسب به تغییر جریان کنترل (control-flow hijacking) یا اجرای کد در همان پروسه منجر شود. در CVE-2026-2757، توانمندی پایه خواندن/نوشتن خارج از محدوده توسط مهاجم قابل دستیابی است.
- اجرای کد احتمالی در فرآیند GMP: این آسیبپذیری از نوع تخریب حافظه است و با شدت Critical ارزیابی شده، اما بدون وجود زنجیره بهرهبرداری عمومی نباید ادعا کرد که مهاجم بهطور قطعی و در همه محیطها به اجرای کد کامل دست مییابد. بیان دقیق این است که چنین باگی میتواند پایهای برای اجرای کد در فرآیند GMP باشد، بهویژه اگر مهاجم بتواند چیدمان هیپ، نشت اطلاعات و مسیرهای کنترلی لازم را مدیریت کند.
- احتمال زنجیرهشدن با فرار از سندباکس (Sandbox Escape): حتی اگر اجرای کد فقط در فرآیند GMP رخ دهد، تحلیل تمام نشده است. مرورگرهای مدرن معمولاً از سندباکس و جداسازی پروسه (process isolation) استفاده میکنند تا اثر باگهای تخریب حافظه محدود شود. با این حال، در حملات واقعی، مهاجم ممکن است یک آسیبپذیری در مکانیزم decoder یا renderer را با یک گریز از سندباکس دیگر ترکیب کند. بنابراین وجود سندباکس شدت فنی باگ را صفر نمیکند؛ بلکه فقط زنجیره بهرهبرداری را پیچیدهتر و سختتر میسازد.
در نتیجه، CVE-2026-2757 از نظر امنیتی اهمیت بالایی دارد، زیرا در نقطهای قرار گرفته که چندین عامل خطرناک با هم ترکیب شدهاند: WebRTC بهعنوان ورودی زمان واقعی و قابل کنترل از راه دور، H.264 بهعنوان یک کدک پیچیده، GMP/OpenH264 بهعنوان مسیر رمزگشایی جداگانه، و در نهایت خطای اعتبارسنجی مرزی (boundary validation) که به سرریز هیپ (heap overflow)، کمبود عدد صحیح (integer underflow) و دسترسی خارج از محدوده منجر میشود. این ترکیب باعث شده آسیبپذیری ارزش تحلیل عمیق داشته باشد.
۱.۶ اطلاعات اجمالی آسیبپذیری
شماره آسیبپذیری: | CVE-2026-2757 |
امتیاز (CVSS): | 9.8 |
مولفه درگیر: | Firefox WebRTC: Audio/Video Component GMP / OpenH264 Decoder Path |
نوع آسیبپذیری: | Incorrect Boundary Conditions Heap Overflow Integer Underflow |
قابلیت در صورت اکسپلویت: | اجرای کد در GMP Process ، Memory Disclosure ، Denial of Service ، احتمال chain شدن با Sandbox Escape |
۱.۷ تحلیلات از پیش ارائه شده
نام تحلیلگر | تاریخ انتشار | لینک |
Joshua Rogers | February 25, 2026 | https://aisle.com/blog/firefox-webrtc-gmp-h264-heap-overflow-via-short-encodedimage-cve-2026-2757 |
۱.۸ مدل کلی تهدید در CVE-2026-2757
مهاجم چه چیزی را کنترل میکند؟ | جلسه WebRTC، تا حدی codec negotiation، و داده/فریم media ورودی. |
قربانی باید در چه شرایطی قرار بگیرد؟ | باید از نسخه آسیبپذیر استفاده کند و مسیر WebRTC Audio/Video؛ مخصوصاً مسیر H.264 decoding درگیر شود. |
آیا احراز هویت لازم است؟ | خیر |
آیا تعامل کاربر لازم است؟ | خیر، در حد باز کردن یک صفحه سایت (html) |
آیا WebRTC باید فعال باشد؟ | بله |
آیا استفاده از H.264 لازم است؟ | بله |
آیا GMP همیشه انتخاب میشود؟ | خیر |
۱.۹ وضعیت Patch و نسخههای آسیبپذیر
برنامه | وضعیت |
Firefox | نسخههای قبل از Firefox 148 آسیبپذیرند. رفع در Firefox 148 انجام شده است. |
Firefox ESR | نسخههای قبل از Firefox ESR 115.33 و Firefox ESR 140.8 آسیبپذیرند. رفع در 115.33 و 140.8 انجام شده است. |
Thunderbird | نسخههای قبل از Thunderbird 148 و Thunderbird 140.8 آسیبپذیرند. رفع در Thunderbird 148 و 140.8 انجام شده است. |
۲. آشنایی با WebRTC
برای درک CVE-2026-2757، پیش از ورود به جزئیات GMP، OpenH264 و ریشه اصلی آسیبپذیری، باید ابتدا مسیر کلی WebRTC را بشناسیم. این آسیبپذیری در مسیر عادی و روزمره «دریافت و پردازش یک جریان ویدیویی (video stream)» در مرورگر رخ میدهد. برای درک و تحلیل صحیح آسیبپذیری، ضروری است که این لایه نیز بهدرستی فهمیده شود.
WebRTC یکی از قابلیتهایی است که مرورگر را از یک ابزار ساده نمایش صفحات وب به یک پلتفرم ارتباطی زمان واقعی (real-time) تبدیل میکند. همین ویژگی، از منظر امنیتی، آن را به یک سطح حمله جدی تبدیل کرده است؛ زیرا مرورگر باید دادههای صوتی، تصویری و شبکهای را با تأخیر بسیار کم (low latency) و بهصورت لحظهای پردازش کند..
۲.۱ فناوری WebRTC چیست؟
فناوری WebRTC مجموعهای از APIها و استانداردها است که به برنامههای وب اجازه میدهد ارتباطات صوتی، تصویری و دادهای را بهصورت زمان واقعی (real-time) برقرار کنند. طبق مستندات MDN (شبکه توسعهدهندگان موزیلا)، WebRTC به وبسایتها و برنامههای وب امکان میدهد رسانههای صوتی/تصویری را ضبط (capture) و پخش (stream) کنند و همچنین دادههای دلخواه (arbitrary data) را بین مرورگرها رد و بدل نمایند، بدون اینکه کاربر نیاز به نصب پلاگین یا نرمافزار جانبی داشته باشد..
به زبان ساده، WebRTC همان قابلیتی است که به یک وباپلیکیشن اجازه میدهد تماس تصویری، تماس صوتی، اشتراکگذاری صفحه، انتقال فایل یا ارتباطات زمان واقعی مستقیم بین کاربران را پیادهسازی کند. نمونههای رایج آن شامل سرویسهای تماس تصویری تحت وب، پلتفرمهای جلسات آنلاین (meeting platforms)، چتهای ویدیویی، ابزارهای پشتیبانی آنلاین و حتی برخی بازیها یا برنامههای مشارکتی (collaborative) هستند.
نکته مهم این است که WebRTC صرفاً یک API سطح بالا نیست. پشت این API، مجموعهای از پروتکلها، مذاکرهها (negotiations)، رمزگذارها (encoders)، رمزگشاها (decoders)، لایههای انتقال (transport layers)، پردازشگرهای بسته (packet processors) و خطوط پردازش رسانه (media pipelines) قرار دارد. همین ترکیب باعث میشود WebRTC از نظر امنیتی بسیار پیچیده باشد؛ زیرا دادهای که از سمت همتا (peer) دیگر میآید، در نهایت باید توسط مرورگر دریافت، تجزیه (parse)، رمزگشایی (decode) و پردازش شود.
۲.۱.۱ بررسی اثبات مفهومی آسیبپذیری WebRTC
در اثبات مفهومی آسیبپذیری WebRTC باید این را نظر بگیریم که این PoC صرفاً یک مفهوم نظری نیست؛ بلکه مسیر واقعی WebRTC با ایجاد دو آبجکت RTCPeerConnection محلی ساخته میشود. یکی از این اتصالها نقش فرستنده و دیگری نقش گیرنده را ایفا میکند. این طراحی هوشمندانه باعث میشود بدون نیاز به همتای خارجی واقعی، مسیر کامل ارسال، دریافت، پردازش و رمزگشایی فریم ویدیویی داخل خود مرورگر Firefox فعال شود. در کد PoC، بخش زیر نقطه شروع ساخت مسیر WebRTC است:
pc1 = new RTCPeerConnection(PC_CONFIG);
pc2 = new RTCPeerConnection(PC_CONFIG);
در این مدل، آبجکت pc1 ویدیو را ارسال میکند و pc2 همان ویدیو را دریافت مینماید. بنابراین، هرچند سناریو بهصورت لوپبک (loopback) و کاملاً محلی اجرا میشود، مسیر دریافت ویدیو در WebRTC و به دنبال آن، مسیر رمزگشایی فریم ویدیویی در مرورگر Firefox فعال میگردد. این نکته از آن جهت برای تحلیل CVE اهمیت دارد که کرش در مرحله پردازش فریم ویدیویی کدگذاریشده در سمت گیرنده رخ میدهد، نه در مرحله نمایش ساده HTML که ارتباطی با کار ما ندارد.
۲.۲ WebRTC در مرورگرها چه کاربردی دارد؟
کاربرد اصلی WebRTC این است که مرورگر بتواند بدون نیاز به پلاگین خارجی، ارتباطات زمان واقعی (real-time) برقرار کند. پیش از ظهور WebRTC، بسیاری از سناریوهای ارتباط صوتی و تصویری در وب نیازمند نرمافزارهای جانبی، پلاگینهای مرورگر یا معماریهای سنگین مبتنی بر سرور بودند. WebRTC این امکان را فراهم کرد که بخش عمدهای از این قابلیتها مستقیماً درون خود مرورگر پیادهسازی شوند.
طبق مشخصات کنسرسیوم وب جهان (W3C)، APIهای WebRTC مجموعهای از رابطهای برنامهنویسی ECMAScript را تعریف میکنند که اجازه میدهند رسانهها و دادههای کاربردی سطح برنامه (application-level data) به مرورگر یا دستگاه دیگری ارسال و از آن دریافت شوند. این یعنی WebRTC فقط محدود به ویدیو نیست؛ بلکه هم رسانههایی مانند صدا و تصویر را پوشش میدهد و هم Data Channel را برای ارسال دادههای غیررسانهای فراهم میکند. در مرورگرها، WebRTC معمولاً برای موارد زیر استفاده میشود:
- تماس صوتی و تصویری
- کنفرانس ویدیویی
- اشتراکگذاری صفحه
- ارتباط مستقیم بین دو مرورگر – همتا (peer-to-peer)
- انتقال داده با تأخیر کم (low latency)
- پخش زنده زمان واقعی (real-time streaming)
- اپلیکیشنهای مشارکتی (collaborative applications)
اما از منظر امنیتی، همین کاربردها پیامد مهمی دارند؛ مرورگر باید دادههایی را پردازش کند که از سمت یک همتای خارجی وارد میشوند. این دادهها ممکن است شامل بستههای شبکه، فریمهای صوتی و تصویری، فرادادههای مربوط به کدک (codec metadata)، توصیف جلسه (session description) و جریانهای پیوسته باشند. هرچه تعداد این مسیرهای پردازش بیشتر باشد، احتمال وجود خطاهای پیادهسازی نیز افزایش مییابد.
در CVE-2026-2757، اهمیت WebRTC دقیقاً از همینجا ناشی میشود. آسیبپذیری در مسیر پردازش صوت/تصویر مربوط به WebRTC در Firefox قرار دارد؛ یعنی در بخشی که مرورگر برای پشتیبانی از ارتباطات ویدیویی زمان واقعی از آن استفاده میکند. این آسیبپذیری نیز بهطور خاص در مسیر رمزگشایی H.264 مربوط به WebRTC در Firefox، هنگام استفاده از GMP Decoder رخ داده است..
۲.۳ ارتباط همتا به همتا در WebRTC
یکی از ویژگیهای اصلی WebRTC، پشتیبانی از ارتباط همتا به همتا است. در این مدل، دو مرورگر یا دو نقطه انتهایی (endpoint) پس از گذراندن مرحله مذاکره (negotiation)، رسانه یا داده را بهصورت مستقیم یا تا حد ممکن مستقیم با یکدیگر رد و بدل میکنند. طبق مستندات MDN، WebRTC امکان تبادل زمان واقعی و همتا به همتا برای صدا، تصویر و داده را فراهم میکند، اما برای آغاز ارتباط همچنان به مرحلهای به نام سیگنالینگ (Signaling) نیاز دارد.
سیگنالینگ بخشی از APIهای WebRTC نیست و مرورگر روش ثابتی برای آن تحمیل نمیکند. برنامه میتواند برای سیگنالینگ از پروتکل WebSocket، پروتکل HTTP، سرور اختصاصی یا هر مکانیسم دیگری استفاده کند. هدف سیگنالینگ این است که دو طرف ارتباط درباره پارامترهای جلسه (session parameters)، کدکها، آدرسهای شبکه، کاندیداها و قابلیتهای خود به توافق برسند.
نکته مهمی که باید دقیق بیان شود این است که همتا به همتا بودن همیشه به معنای ارتباط کاملاً مستقیم بدون هیچ سروری نیست. در بسیاری از شبکهها، به دلیل NAT، فایروال یا محدودیتهای شبکه، WebRTC ممکن است از STUN یا TURN استفاده کند. STUN یا Session Traversal Utilities for NAT برای کشف مسیر ارتباطی و TURN یا Traversal Using Relays around NAT برای رله کردن ترافیک در شرایطی به کار میرود که ارتباط مستقیم ممکن نباشد. با این حال، مدل اصلی WebRTC همچنان بر ایجاد ارتباط زمان واقعی بین همتاها استوار است.
از منظر امنیتی، همتا به همتا بودن نکته مهمی دارد: همتای مقابل میتواند روی بخشی از دادههای رسانه اثر بگذارد. البته این به معنای کنترل کامل بر همه اجزای داخلی مرورگر نیست، اما به این معنی است که مرورگر باید دادهای را پردازش کند که از سمت طرف مقابل ارتباط آمده است. در آسیبپذیریهایی مانند CVE-2026-2757، همین مسئله اهمیت زیادی دارد؛ زیرا مهاجم بالقوه میتواند در یک سناریوی WebRTC، داده ویدیویی خاص یا ناقص (malformed) را وارد مسیر پردازش کند..
۲.۴ انتقال جریانهای صوتی و تصویری در WebRTC
در WebRTC، صدا و تصویر معمولاً در قالب ترکهای رسانهای (Media Tracks) منتقل میشوند. این ترکها میتوانند از دوربین، میکروفون، اشتراکگذاری صفحه یا منابع دیگر تولید شوند و سپس از طریق یک RTCPeerConnection به همتای مقابل ارسال گردند.
// ADTSTrackDemuxer
ADTSTrackDemuxer:: ADTSTrackDemuxer (MediaResource* aSource)
: mSource(aSource),
mParser(new ADTS:: FrameParser()),
mOffset(0),
mNumParsedFrames (0), 75
mFrameIndex(0), 76
mTotalFrameLen(0), 77
mSamplesPerFrame (0),
mSamples PerSecond (0),
mChannels (0) {
DDLINKCHILD("source", aSource);
Reset();
}
در تصویر زیر این مراحل مصورسازی شده است تا مراحل به درستی درک شود. با این حال، در سمت دریافتکننده نیز مرورگر باید جریان ورودی را دریافت، رمزگشایی و برای پخش آماده کند. این روند در تمامی ابعاد تکرار میشود.
در سمت ارسال، مرورگر باید رسانه خام را رمزگذاری کند. برای مثال، تصویر دوربین ممکن است با کدکهایی مانند VP8، VP9، AV1 یا H.264 فشرده شود. سپس دادههای رمزگذاریشده در بستههای مناسب قرار گرفته و از طریق لایه انتقال امن WebRTC ارسال میشوند. در قطعه کد زیر، تابعی که نقش رمزگذاری داده را بر عهده دارد، نمایش داده شده است.
int32_t H264Encoder Impl:: Encode(
const VideoFrame& input_frame,
const std::vector* frame_types) {
if (encoders_.empty()) {
ReportError();
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
if (!encoded_image_callback_) {
RTC_LOG(LS_WARNING)
<<< "InitEncode() has been called, but a callback function "
"has not been set with RegisterEncodeCompleteCallback()";
ReportError();
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
scoped_refptr frame_buffer
input_frame.video_frame_buffer()->To1420();
if (!frame_buffer) {
RTC_LOG(LS_ERROR) << "Failed to convert "
<< VideoFrameBufferTypeToString(
input_frame.video_frame_buffer()->type())
<<< " image to 1420. Can't encode frame.";
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
if (frame_buffer->StrideU() != frame_buffer->StrideV()) {
// TODO: crbug.com/chromium: 491655161 Remove once the root cause is fixed.
RTC_LOG(LS_ERROR) << "OpenH264 requires the U and V strides to be equal.";
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
RTC_CHECK(frame_buffer->type() VideoFrameBuffer::Type::kI420 ||
frame_buffer->type() == VideoFrameBuffer::Type::kI420A);
bool is_keyframe_needed = false;
for (size_t i = 0; i < configurations_.size(); ++i) {
if (configurations_[i].key_frame_request && configurations_[i].sending) {
// This is legacy behavior, generating a keyframe on all layers 464
// when generating one for a layer that became active for the first time 465
// or after being disabled. 466
is_keyframe_needed true;
break;
در سمت دریافت، همین مسیر به صورت معکوس طی میشود: بستهها دریافت میشوند، فریمهای رسانه بازسازی میگردند، رمزگشای مناسب انتخاب میشود و در نهایت خروجی صوتی یا تصویری تولید میگردد. بخشی از تابع که در سمت دریافت کننده نقش رمزگشایی فریم را بر عهده دارد، در قطعه کد زیر نمایش داده شده است:
void WebrtcGmpVideoDecoder:: Decoded (GMPVideoi420Frame* aDecodedFrame) {
// we have two choices here: wrap the frame with a callback that frees
// the data later (risking running out of shmems), or copy the data out
// always. Also, we can only Destroy() the frame on the gmp thread, so
// copying is simplest if expensive.
// 1420 size including rounding...
CheckedInt32 length = (CheckedInt32(aDecodedFrame->Stride (KGMPYPlane)) *
aDecodedFrame->Height()) +
(CheckedInt32(aDecodedFrame->Stride (kGMPVPlane)) +
aDecodedFrame->Stride (KGMPUPlane)) *
((aDecodedFrame->Height() + 1) / 2);
int32_t size length.isValid() ? length.value(): 0;
MOZ_RELEASE_ASSERT(length.isValid() && size > 0);
// Don't use MakeUniqueFallible here, because UniquePtr isn't copyable, and
// the closure below in WrapI420Buffer uses std:: function which is copyable.
// We'll alloc the buffer here, so we preserve the "fallible" nature, and
// then hand a shared_ptr, which is copyable, to WrapI420Buffer.
auto* falliblebuffer = new (std::nothrow) uint8_t[size];
if (falliblebuffer) {
auto buffer = std::shared_ptr(falliblebuffer);
// This is 3 separate buffers currently anyways, no use in trying to
// see if we can use a single memcpy.
uint8_t* buffer_y = buffer.get();
memcpy(buffer_y, aDecoded Frame->Buffer(kGMPYPlane),
aDecoded Frame->Stride (KGMPYPlane) * aDecodedFrame->Height());
// Should this be aligned, making it non-contiguous? Assume no, this is
// already factored into the strides.
uint8_t* buffer_u =
buffer_y + aDecodedFrame->Stride (kGMPYPlane) * aDecodedFrame->Height();
memcpy(buffer_u, aDecodedFrame->Buffer(kGMPUPlane),
aDecoded Frame->Stride (KGMPUPlane) *
((aDecodedFrame->Height() + 1) / 2));
uint8_t* buffer_v = buffer_u + aDecodedFrame->Stride (kGMPUPlane) *
((aDecodedFrame->Height() + 1) / 2));
memcpy(buffer_v, aDecodedFrame->Buffer (KGMPVPlane),
aDecoded Frame->Stride (KGMPVPlane) *
((aDecodedFrame->Height() + 1) / 2);
MutexAutoLock lock(mCallbackMutex);
MDN در توضیح RTCRtpSender میگوید که این رابط امکان کنترل و دریافت جزئیات مربوط به نحوه رمزگذاری و ارسال یک MediaStreamTrack به همتای دور را فراهم میکند. در سمت مقابل، RTCRtpReceiver مسئول دریافت و رمزگشایی دادهها برای یک MediaStreamTrack روی RTCPeerConnection است. این دو رابط نشان میدهند که در WebRTC، رمزگذاری و رمزگشایی رسانه بخش اصلی و جداییناپذیر مسیر ارتباطی است.
ارتباط این بخش با CVE-2026-2757 کاملاً واضح است؛ آسیبپذیری در مرحلهای رخ میدهد که داده ویدیویی رمزگذاریشده باید رمزگشایی شود. یعنی مشکل نه در سطح رابط کاربری یا برنامه جاوااسکریپت، بلکه در لایه پایینتر پردازش رسانه (media processing) قرار دارد؛ جایی که بافرها، فریمها و اندازه دادهها اهمیت مستقیم امنیتی پیدا میکنند.
۲.۴.۱ تولید Video Track کنترل شده در PoC
در کد اثبات مفهومی، منبع ویدیو از دوربین یا فایل خارجی گرفته نمیشود. برای اینکه PoC قابل تکرارتر باشد و به مجوز دوربین وابسته نباشد، یک Canvas (بوم) ساخته میشود و خروجی آن بهعنوان MediaStreamTrack وارد WebRTC میگردد. بخش مربوطه در PoC به شکل زیر است:
canvas = document.createElement('canvas');
canvas.width = 640;
canvas.height = 360;
…
…
…
stream = canvas.captureStream(30);
videoTrack = stream.getVideoTracks()[0];
تابع captureStream باعث میشود محتوای canvas بهصورت یک جریان ویدیویی با نرخ تقریبی ۳۰ فریم بر ثانیه تولید شود. سپس اولین ترک ویدیویی از این جریان گرفته شده و به RTCPeerConnection داده میشود. در نتیجه، PoC یک جریان ویدیویی واقعی برای WebRTC ایجاد میکند، اما ورودی آن کاملاً کنترلشده و مستقل از سختافزار یا مجوز دوربین است.
۲.۵ نقش RTP در انتقال Media
پروتکل RTP (Real-time Transport Protocol) پروتکلی است که برای انتقال دادههای زمان واقعی (real-time) مانند صدا و تصویر طراحی شده است. در WebRTC، رسانه از طریق RTP منتقل میشود، اما نکته مهم این است که WebRTC از نسخه امن آن یعنی SRTP یا Secure Real-time Transport Protocol استفاده میکند. در تصویر 5، پیادهسازی کلاس SRTP در Firefox نمایش داده شده است. مستندات MDN در مقدمه RTP برای WebRTC تأکید میکند که WebRTC در عمل از SRTP استفاده میکند تا دادههای تبادلشده امن و احراز هویتشده باشند. RTP برای انتقال رسانه چند نقش مهم دارد:
- تقسیم رسانه رمزگذاریشده به بستههای قابل انتقال
- نگهداری اطلاعات زمانی (timestamping) برای پخش صحیح صدا/تصویر
- مشخص کردن ترتیب بستهها (sequencing)
- کمک به بازسازی جریان در سمت دریافتکننده
- حمل پیلود یا محموله (payload) مربوط به کدک مشخصشده
در کنار RTP، معمولاً پروتمل RTCP یا RTP Control Protocol نیز برای کنترل و بازخورد استفاده میشود. پزوتکل RTCP میتواند اطلاعاتی مانند کیفیت ارتباط، از دست رفتن بستهها (packet loss)، jitter و وضعیت دریافت جریان را منتقل کند. این بازخوردها برای تنظیم کیفیت، بیتریت و پایداری تماس زمان واقعی اهمیت دارند.
class SrtpFlow {
~SrtpFlow();
public:
static unsigned int KeySize(int cipher_suite);
static unsigned int SaltSize(int cipher_suite);
static RefPtr Create(int cipher_suite, bool inbound,
const void* key, size_t key_len);
nsresult ProtectRtp (void* in, int in_len, int max_len, int* out_len);
nsresult UnprotectRtp (void* in, int in_len, int max_len, int* out_len);
nsresult ProtectRtcp(void* in, int in_len, int max_len, int* out_len); 49
nsresult UnprotectRtcp (void* in, int in_len, int max_len, int* out_len);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING (SrtpFlow)
static void srtp_event_handler(srtp_event_data_t* data);
private:
SrtpFlow(): session_(nullptr) {}
nsresult CheckInputs (bool protect, void* in, int in_len, int max_len,
int* out_len);
static nsresult Init();
static bool initialized; // Was libsrtp initialized? Only happens once.
srtp_t session_; 65
};
} // namespace mozilla
#endif
در WebRTC، پروتکل RTP فقط یک کانال خام برای ارسال بایت نیست. بستههای RTP در نهایت حامل پیلودهای مفید رمزگذاریشدهای هستند که باید توسط رمزگشای مناسب تفسیر شوند. اگر پیلود مربوط به H.264 باشد، سمت دریافتکننده باید مسیر رمزگشایی مناسب برای H.264 را فعال کند. همین نقطه برای ما نیز مهم است، زیرا CVE-2026-2757 مربوط به مسیر رمزگشایی H.264 در WebRTC فایرفاکس است.
RTCRtpTransceiver نیز در WebRTC یک انتزاع مهم است، زیرا یک فرستنده و گیرنده را با وضعیت مشترک مربوط به یک بخش رسانه ترکیب میکند. MDN توضیح میدهد که هر بخش رسانه در SDP یک جریان دوطرفه SRTP را توصیف میکند و transceiver این جفتسازی بین ارسال و دریافت را نشان میدهد.
49/**
* This is what ties all the various pieces that make up a transceiver
* together. This includes:
* MediaStreamTrack for rendering and capture
* MediaTransportHandler for RTP transmission/reception
* Audio/VideoConduit for feeding RTP/RTCP into webrtc.org for decoding, and
* feeding audio/video frames into webrtc.org for encoding into RTP/RTCP.
*/
class RTCRtpTransceiver public nsISupports, public nsWrapperCache {
public:
/**
*|aSendTrack might or might not be set.
*/
RTCRtpTransceiver(
nsPIDOMWindowInner* aWindow, bool aPrivacy Needed, PeerConnectionImpl* aPc,
MediaTransportHandler* aTransportHandler, JsepSession* aJsepSession,
const std::string& aTransceiverId, bool alsVideo,
nsISerialEventTarget* aStsThread, MediaStreamTrack* aSendTrack,
WebrtcCallWrapper* aCallWrapper, RTCStatsIdGenerator* aIdGenerator);
void Init(const RTCRtpTransceiverInit& aInit, ErrorResult& aRv);
bool IsValid() const { return !! mConduit; }
nsresult Update Transport();
nsresult UpdateConduit();
void UpdatePrincipal Privacy (PrincipalPrivacy aPrivacy);
void ResetSync();
nsresult SyncWithMatchingVideoConduits (
nsTArray>& transceivers);
void Close();
void BreakCycles();
void Unlink();
bool ConduitHasPluginID (uint64_t aPluginID);
به زبان ساده، RTP/SRTP همان لایهای است که رسانه رمزگذاریشده را از همتای مقابل به مرورگر میرساند. اما آسیبپذیری مورد بحث در خود RTP نیست؛ مشکل زمانی رخ میدهد که پیلود دریافتشده وارد مسیر رمزگشایی و پردازش داخلی فایرفاکس میشود.
۲.۶ مذاکره کدک چیست؟
Codec Negotiation فرایندی است که طی آن دو همتا (peer) درباره کدکها و پارامترهای قابل استفاده برای ارتباط رسانه به توافق میرسند. برای اینکه دو مرورگر بتوانند تماس ویدیویی برقرار کنند، باید حداقل روی یک کدک مشترک توافق داشته باشند. اگر یک طرف فقط از کدک خاصی پشتیبانی کند و طرف دیگر آن را پشتیبانی نکند، رسانه بهدرستی منتقل یا رمزگشایی نخواهد شد.
این مذاکره معمولاً از طریق SDP (Session Description Protocol) انجام میشود. SDP اطلاعات مربوط به جلسه رسانه را توصیف میکند؛ از جمله نوع رسانه، آدرسها، پورتها، فرمتها، کدکها و پارامترهای مرتبط. مستندات MDN توضیح میدهد که SDP برای توصیف محتوای اتصال چندرسانهای (multimedia connection) مانند رزولوشن، فرمت، کدک و رمزنگاری استفاده میشود تا دو طرف پیش از انتقال داده بتوانند یکدیگر را درک کنند.
در یک ارتباط WebRTC، هر طرف فهرستی از کدکهای قابل پشتیبانی خود را ارائه میدهد. سپس بر اساس مدل Offer/Answer، اولویتها و قابلیتهای دو طرف، کدک نهایی انتخاب میشود. برای ویدیو، کدکهایی مانند VP8، VP9، H.264 یا AV1 ممکن است مطرح شوند. انتخاب H.264 در این CVE اهمیت زیادی دارد، زیرا آسیبپذیری مورد بحث در مسیر رمزگشایی H.264 مربوط به WebRTC، هنگام استفاده از GMP Decoder رخ میدهد.
از نظر امنیتی، مذاکره کدک اهمیت بالایی دارد. زیرا اگر مهاجم بتواند شرایطی ایجاد کند که یک مسیر رمزگشای خاص انتخاب شود، سطح حمله از یک بخش عمومی WebRTC به یک کامپوننت خاصتر مانند H.264 Decoder یا مسیر GMP Decoder منتقل میشود. البته باید دقیق بود؛ این به معنای آن نیست که مهاجم همیشه و در همه شرایط بتواند رمزگشای فایل فرمت رسانه دلخواه خود را تحمیل کند. انتخاب مسیر رمزگشایی به عوامل متعددی مانند تنظیمات مرورگر، پلتفرم، بکاندهای فعال، شتابدهی سختافزاری (hardware acceleration) و مکانیسمهای جایگزین (fallback mechanisms) بستگی دارد. اما مذاکره کدک میتواند بر مسیر پردازش اثر بگذارد و به همین دلیل در تحلیل قابلیت بهرهبرداری (exploitability) باید مورد بررسی قرار گیرد.
۲.۶.۱ ولویت دادن به H.264 در PoC
چون CVE-2026-2757 در مسیر WebRTC H.264 و هنگام استفاده از مسیر رمزگشای GMP/OpenH264 رخ میدهد، PoC تلاش میکند کدک مربوط به H.264 را در اولویت قرار دهد. این کار با گرفتن قابلیتهای ویدیویی (video capabilities) و جداسازی کدکهایی انجام میشود که mimeType آنها برابر video/H264 است. قسمت مربوطه در PoC به شکل زیر است:
const caps = RTCRtpReceiver.getCapabilities('video');
const h264 = caps.codecs.filter(c = > (c.mimeType || '').toLowerCase() === 'video/h264');
const helpers = caps.codecs.filter(c = > {
const m = (c.mimeType || '').toLowerCase();
return ( m === 'video/rtx' || m === 'video/red' || m === 'video/ulpfec');
});
txPc1.setCodecPreferences([...h264,...helpers]);
این کد باعث میشود H.264 در اولویت کدکهای قابل استفاده قرار بگیرد.
۳. معماری پردازش رسانه در Firefox
برای تحلیل CVE-2026-2757، دانستن اینکه یک فریم ناقص باعث سرریز هیپ شده است کافی نیست. باید بدانیم این فریم از کجا وارد فایرفاکس میشود، در چه قالبی بین لایهها جابهجا میگردد، کدام کامپوننتها آن را پردازش میکنند و در نهایت خطا در کدام مرز اعتماد (trust boundary) رخ داده است.
class MediaFormatReader final
: public Supports ThreadSafeWeakPtr,
public DecoderDoctorLifeLogger {
static const bool IsExclusive = true;
using TrackType = TrackInfo:: TrackType;
using Notify DataArrivedPromise = MozPromise;
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME (MediaFormatReader)
using TrackSet = EnumSet;
using MetadataPromise = MozPromise;
template
using DataPromise = MozPromise, MediaResult, IsExclusive>;
using AudioDataPromise = DataPromise;
using VideoDataPromise = DataPromise;
using SeekPromise = MozPromise;
// Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
// But in the current architecture it's only ever used exclusively (by MDSM),
// so we mark it that way to verify our assumptions. If you have a use-case
// for multiple WaitForData consumers, feel free to flip the exclusivity here.
using WaitForDataPromise =
MozPromise;
MediaFormatReader (MediaFormatReaderInit& aInit, MediaDataDemuxer* aDemuxer);
virtual ~MediaFormatReader();
// Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
// on failure.
nsresult Init();
size_t SizeOfVideoQueueInFrames();
size_t SizeOfAudioQueueInFrames();
// Requests one video sample from the reader.
RefPtr RequestVideoData(
const media:: TimeUnit& aTimeThreshold,
bool aRequestNextVideoKeyFrame = false);
// Requests one audio sample from the reader.
//
// The decode should be performed asynchronously, and the promise should
// be resolved when it is complete.
RefPtr RequestAudioData();
فایرفاکس برای پردازش رسانه از چندین مسیر و بکاند مختلف استفاده میکند. مسیر عمومی پخش فایلهای رسانه، مانند ویدیوهای HTML5، معمولاً شامل دریافت منبع، جداسازی (Demultiplexing)، رمزگشایی و رندر است. در مستندات سورس فایرفاکس، MediaFormatReader بهعنوان بخشی معرفی شده که نمونههای رمزگشاییشده لازم برای پخش رو به جلو را از منبع رسانه فراهم میکند و بین حالتهایی مانند demux، decode، drain و error جابهجا میشود. در 5-B بخشی از کد این کلاس نمایش داده شده است.
اما مسیر WebRTC کمی متفاوت است. در WebRTC، داده معمولاً از یک همتای دیگر و در قالب جریان زمان واقعی (real-time stream) دریافت میشود، نه لزوماً از یک فایل یا کانتینر سنتی مانند MP4 یا WebM. با این حال، در هر دو حالت یک اصل مشترک وجود دارد: داده رمزگذاریشده در نهایت باید وارد یک رمزگشا شود و رمزگشا آن را به فریم قابل استفاده برای پخش تبدیل کند.
در CVE-2026-2757، مسئله دقیقاً در همین نقطه رخ میدهد؛ داده ویدیویی رمزگذاریشده، در مسیر WebRTC H.264، بهصورت یک EncodedImage وارد رمزگشا میشود و در مسیر GMP به GMPVideoEncodedFrame تبدیل میگردد. در این CVE، مرحله بستهبندی و تحویل داده به GMP دقیقاً جایی است که خطای شرایط مرزی (boundary condition) رخ داده است.
۳.۱ خط پردازش رسانه در Firefox
خط پردازش رسانه یا Media Pipeline در فایرفاکس را میتوان مجموعهای از لایهها دانست که دادههای رسانهای را از حالت خام یا رمزگذاریشده دریافت میکنند، آنها را تجزیه و رمزگشایی میکنند و در نهایت خروجی قابل پخش تولید مینمایند. در مسیرهای عمومی پخش رسانه، این خط پردازش معمولاً شامل کامپوننتهایی مانند منبع رسانه (media resource)، تفکیک کننده (demuxer)، رمزگشا، ماشین حالت (state machine) و renderer است. بهصورت ساده، در یک مسیر عمومی پخش ویدیو، معماری میتواند به شکل زیر دیده شود:
در این مدل، تفکیک کننده یا demuxer وظیفه دارد کانتینر را باز کند و نمونههای رمزگذاریشده را بیرون بکشد. ماژول رمزگشای سپس این نمونهها را به فریمهای قابل پخش تبدیل میکند. این همان مسیر کلاسیک است که در پخش فایلهای رسانه یا جریانهای مبتنی بر کانتینر دیده میشود، اما WebRTC معمولاً با کانتینرهای کلاسیک کار نمیکند. در WebRTC، رسانه بهصورت جریان و بستههای زمان واقعی منتقل میشود. بنابراین مسیر آن بیشتر شبیه به شکل زیر است:
در CVE-2026-2757، تمرکز روی همین مسیر دوم یعنی مسیر WebRTC است. داده ویدیویی H.264 از سمت همتا وارد استک WebRTC میشود، به شکل فریم رمزگذاریشده در اختیار ماژول رمزگشا قرار میگیرد و در شرایط خاص از مسیر GMP Decoder عبور میکند. همانطور که پیش از این ذکر شد، نکته مهم این است که فایرفاکس فقط یک رمزگشای ثابت ندارد. بسته به کدک، پلتفرم، تنظیمات، قابلیتهای سیستمعامل، شتابدهی سختافزاری و مکانیسمهای جایگزین داخلی، مسیر رمزگشایی میتواند متفاوت باشد. به همین دلیل در تحلیل این CVE باید مشخص کنیم که آسیبپذیری در مسیر WebRTC H.264 هنگام استفاده از GMP Decoder Path رخ داده است.
۳.۲ مسیر کلی دریافت تا رمزگشایی فریم در فایرفاکس
در یک ارتباط WebRTC، زمانی که همتای مقابل یک جریان ویدیویی ارسال میکند، داده بهصورت بستههای شبکه وارد مرورگر میشود. این بستهها معمولاً حامل دادههای رمزگذاریشده هستند. مرورگر ابتدا باید بستهها را دریافت و مرتب کند، سپس فریمهای رمزگذاریشده را بازسازی نماید و در نهایت آنها را به رمزگشای مناسب تحویل دهد. مسیر سادهشده به شکل زیر است:
اگر کدک انتخابشده H.264 باشد، داده رمزگذاریشده باید وارد مسیر رمزگشایی H.264 شود. حالا بسته به محیط، فایرفاکس ممکن است از بکاندهای مختلفی برای رمزگشایی استفاده کند؛ مثلاً رمزگشای سیستمعامل، مسیرهای داخلی، یا در برخی شرایط مسیر جایگزین مبتنی بر GMP/OpenH264.
در مورد CVE-2026-2757، وقتی WebRTC یک فریم رمزگذاریشده H.264 دریافت میکند، این فریم بهصورت webrtc::EncodedImage نمایش داده میشود و به پیادهسازی ماژول رمزگشایی تحویل داده میشود. در مسیر GMP، فایرفاکس این داده را در قالب GMPVideoEncodedFrame بستهبندی میکند و از مرز GMP عبور میدهد تا در فرآیند پلاگین (plugin process) رمزگشایی شود. پس مسیر مربوط به این CVE را میتوان مانند قطعه کد زیر خلاصه کرد.
// XXX At this point, we only will get model data (a single length and a 1027
// buffer) Session_info.cc/etc code needs to change to support mode 0. 1028
*(reinterpret_cast(frame->Buffer())) = frame->Size(); 1029
// XXX It'd be wonderful not to have to memcpy the encoded data! 1031
memcpy(frame->Buffer() + 4, aDecodeData->mImage.data() + 4, 1032
frame->Size() - 4);
frame->SetEncodedWidth (aDecodeData->mImage._encodedWidth);
frame->SetEncodedHeight(aDecodeData->mImage._encodedHeight); 1036
frame->SetTimeStamp((aDecodeData->mImage.RtpTimestamp() * 100011) /
90); // rounds down
frame->SetCompleteFrame(
true); // upstream no longer deals with incomplete frames
frame->SetBufferType(GMP_BufferLength32);
GMPVideoFrameType ft;
int32_t ret =
WebrtcFrameTypeToGmpFrameType (aDecodeData->mImage._frameType, &ft);
if (ret != WEBRTC_VIDEO_CODEC_OK) {
GMP_LOG_ERROR("{}: WebrtcFrameTypeToGmpFrameType failed ({})!",
___PRETTY_FUNCTION_, ret);
mDecoderStatus = GMPDecodeErr;
return;
}
مشکل امنیتی دقیقاً از همین مرحله تبدیل و بستهبندی بین EncodedImage و GMPVideoEncodedFrame آغاز میشود. کد آسیبپذیر فرض کرده بود که بافر ورودی حداقل به اندازهای است که بتوان یک هدر چهار بایتی در آن نوشت و سپس size – 4 بایت را کپی کرد. اما وقتی اندازه ورودی فقط 1 تا 3 بایت باشد، این فرض نادرست خواهد بود. در تصویر 8-A کد آسیبپذیر آورده شده است.
۳.۳ فریم رمزگذاری شده چیست؟
برای فهم بهتر این آسیبپذیری، باید تفاوت فریم encode شده و فریم decode شده روشن باشد. یک decoded frame فریمی است که آماده پردازش یا نمایش است. مثلاً یک تصویر خام ویدیویی که میتواند به renderer داده شود. چنین فریمی معمولاً حجم بیشتری دارد، چون داده فشرده نیست یا تا حد زیادی از حالت فشرده خارج شده است.
در مقابل، یک فریم رمزنگاری شده یا فریم رمزگذاری شده، به عبارتی فریمی است که هنوز در قالب codec فشردهشده قرار دارد. مثلاً اگر codec ویدیو H.264 باشد، فریم رمزنگاری شده شامل دادهای است که باید توسط H.264 رمزگشای تفسیر شود. این داده برای نمایش مستقیم مناسب نیست و باید رمزگشایی شود. بهصورت ساده فریم رمزگذاری شده یعنی داده فشردهشده، وابسته به codec، مناسب برای انتقال و Decoded Frame یعنی داده بازشده، آماده برای پردازش یا نمایش توسط Firefox به شمار میروند.
در WebRTC، انتقال داده روی شبکه معمولاً با فریمهای رمزنگاری شده انجام میشود؛ چون ارسال ویدیوی خام از نظر پهنای باند غیرعملی است. بنابراین سمت گیرنده باید این فریمهای رمزنگاری شده را دریافت کند و به ماژول رمزگشا بدهد. از نظر امنیتی، فریمهای رمزنگاری شده مهم هستند چون مستقیماً از سمت همتا خارجی میآیند و ساختارشان توسط رمزگشا تفسیر میشود. اگر ماژول رمزگشا یا wrapper قبل از رمزگشا فرض اشتباهی درباره اندازه یا ساختار این داده داشته باشد، همان فریم رمزنگاری شده میتواند به ورودی مخرب تبدیل شود. در CVE-2026-2757، فریم مخرب از نظر مفهومی یک فریم رمزنگاری شده با استاندارد h.264 بسیار کوتاه است؛ یعنی دادهای که به اندازه کافی بزرگ نیست، اما از بررسیهای اولیه رمزگشا عبور میکند و به کدی میرسد که حداقل 4 بایت را برای فریم فرض گرفته است.
۳.۴ EncodedImage چیست؟
EncodedImage یک ساختار یا مفهوم انتزاعی برای نمایش فریم ویدیویی رمزگذاریشده است. در سورس کد WebRTC، مفهوم EncodedImage به این صورت توضیح داده شده است: یک فریم رمزگذاریشده از جریان ویدیویی که بهعنوان ورودی برای رمزگشاها و خروجی برای رمزگذارها استفاده میشود. به عبارت ساده:
Encoder Output --> EncodedImage --> Decoder Input
برای مثال تفاوت مسیر Encode و Decode در پردازش ویدیو را میتوان در گراف زیر مشاهده کرد.
در مسیر CVE-2026-2757، EncodedImage همان ظرفی است که داده H.264 رمزنگاری شده را حمل میکند. این داده سپس توسط Firefox به مسیر GMP decoder داده میشود. مشکل از اینجا شروع میشود که EncodedImage میتواند اندازهای کمتر از حد انتظار داشته باشد؛ مثلاً 1، 2 یا 3 بایت. به بیان دقیقتر میتوان گفت که ()WebrtcGmpVideoDecoder::Decode_g میتواند با EncodedImageهای بسیار کوچک، یعنی 1 تا 3 بایت، فراخوانی شود. این ورودیهای کوچک باعث میشدند نوشتن header چهار بایتی از محدوده تخصیص حافظه خارج شود و سپس محاسبه size – 4 به underflow برسد. این مسئله در تصویر 8-A نمایش داده شده است.
EncodedImage تنها یک buffer ساده نیست، EncodedImage نماینده یک فریم ویدیویی رمزنگاری شده در WebRTC است که فراداده و بافر حافظه مربوط به فریم را حمل میکند و در مرز بین رمزگذار، رمزگشا و glue codeهای مرورگر اهمیت امنیتی پیدا میکند. این تعریف برای ادامه مهم است، زیرا که ریشه این آسیبپذیری دقیقاً به اعتبارسنجی ناکافی اندازه همین EncodedImage مربوط میشود.
۳.۴.۱ نگاشت frame.data در PoC به EncodedImage در فایرفاکس
در PoC، داده فریم رمزگذاری شده قبل از رسیدن به ماژول رمزگشا با استفاده از WebRTC Encoded Transform تغییر داده میشود. بخش اصلی trigger اینجاست:
const originalLen = frame?.data?.byteLength ?? -1;
if (originalLen > 3) {
frame.data = frame.data.slice(0, randInt(1, 3));
}
controller.enqueue(frame);
در این کد، frame.data همان داده رمزگذاری شدهای است که هنوز رمزگشایی نشده است. کد مفهومی یا PoC عمداً این داده را به ۱، ۲ یا ۳ بایت کوتاه میکند و سپس همان فریم کوتاه شده را دوباره وارد ادامه خط پردازش مرورگر Firefox یا همان Processing Pipeline میکند. وقتی این فریم در مسیر فایرفاکس به رمزگشا داده میشود، اندازه آن در سمت ++C به شکل زیر دیده میشود:
aInputImage.size()
aDecodeData->mImage.size()
بنابراین ارتباط مستقیم میان PoC و کد آسیبپذیر این است:
این نقطه همان جایی است که ورودی کوتاه و کنترل شده از سطح JavaScript/WebRTC به سطح ++C و مسیر WebrtcGmpVideoDecoder منتقل میشود. از نظر امنیتی، این مهمترین مرز داده در تحلیل CVE است، چون داده هنوز رمزگذاری شده و غیرقابل اعتماد است، اما چند خط بعد در مسیر GMP با فرض حداقل اندازه 4 بایت پردازش میشود.
۳.۵ انتخاب رمزگشا در Firefox
انتخاب رمزگشا یا Decoder Selection به این معناست که فایرفاکس تصمیم بگیرد برای رمزگشایی یک فریم از کدام بکاند استفاده کند. در تصویر زیر این مسئله در سطح کد به صورت جزیی نمایش داده شده است:
// OpenH264 officially supports both decode and encode up to level 5.2.
static constexpr H264_LEVEL kOpenH264MaxLevel = H264_LEVEL::H264_LEVEL_5_2;
media:: DecodeSupportSet WebrtcGmpDecoder Supports(
const MediaExtended MIME Type& aMime, const SupportDecoderParams&) {
if (!HaveGMPFor("decode-video"_ns, {"h264"_ns})) {
return {};
}
const auto fmtp ParseH264Fmtp(aMime. OriginalString()); 40
if (fmtp.mProfileLevel.isErr() && 41
fmtp.mProfileLevel.inspectErr() == H264FmtpParseError:: Invalid) { 42
return {}; 43
}
if (fmtp.mProfileLevel.isok()) { 45
const auto& pl = fmtp.mProfileLevel.inspect();
if (pl.mProfile > H264_PROFILE:: H264_PROFILE_HIGH) {
return {};
}
if (pl.mLevel > kOpenH264MaxLevel) {
return {};
}
}
return media:: DecodeSupport:: SoftwareDecode;
}


