กลับ
2026/10/28
Node2Shell (CVE-2026-111497): ระบบใดบ้างที่มีความเสี่ยง และควรทำอะไรทันที
CVE-2026-111497 ใน Brotli ส่งผลต่อระบบใดจริง ความเร่งด่วนของแต่ละกรณี และขั้นตอนแพตช์ บิลด์ใหม่ รีสตาร์ท และลดความเสี่ยงทันที
อัปเดตเมื่อ 27 ตุลาคม 2026
CVE-2026-111497 หรือที่รู้จักในชื่อ “Node2Shell” หรือ “HTTP2Shell” เป็นบั๊กหน่วยความจำเสียหาย (memory corruption) ในตัวคลายการบีบอัด Brotli โดย Brotli คือการบีบอัดแบบ br ที่ใช้กันทั่วทั้งเว็บ บั๊กนี้อยู่ในไลบรารี Brotli ของ Google ตั้งแต่เวอร์ชัน 1.0.3 ถึง 1.2.0 [1] Node.js รวมไลบรารีนี้มาในตัว และโปรเจกต์ Node.js จัดระดับปัญหานี้เป็น High (สูง) สำหรับสาย 22.x, 24.x และ 26.x [2] ตัวถอดรหัสเดียวกันนี้ยังถูกรวมอยู่ในแพ็กเกจ Python, ไลบรารีระบบของ Linux, แอปเดสก์ท็อป และเครื่องมือสำหรับนักพัฒนา ดังนั้นขอบเขตความเสี่ยงที่แท้จริงจึงกว้างกว่า “เซิร์ฟเวอร์ Node.js” มาก
บทความนี้เหมาะสำหรับทีมที่ต้องตัดสินใจอย่างรวดเร็วว่าตนได้รับผลกระทบหรือไม่ และควรทำอะไรเป็นอันดับแรก
สรุปสั้น ๆ: หากมีระบบใดของคุณคลายการบีบอัดข้อมูล Brotli ที่มาจากฝ่ายที่คุณควบคุมไม่ได้ (ไคลเอนต์บนอินเทอร์เน็ต เว็บไซต์ภายนอก ผู้ส่ง webhook หรือไฟล์ที่ถูกอัปโหลด) ให้ถือว่าเป็นเรื่องเร่งด่วน แพตช์ บิลด์ใหม่ รีสตาร์ท และระหว่างนี้ให้บล็อก br ไว้ก่อน
ช่องโหว่นี้ทำงานอย่างไร
ตัวถอดรหัสจัดการ “block switch” ที่มีรูปแบบผิดพลาดในสตรีมข้อมูลที่ถูกบีบอัดอย่างไม่ถูกต้อง โดยมองข้อผิดพลาดนั้นว่าเป็น “ต้องการอินพุตเพิ่ม” แทนที่จะเป็น “ข้อมูลนี้ไม่ถูกต้อง” และเขียนไบต์ต่อท้ายลงในบัฟเฟอร์ภายในขนาดเล็กที่มีขนาดคงที่ไปเรื่อย ๆ จนเขียนเกินขอบท้ายของบัฟเฟอร์ [2] ผู้โจมตีที่สามารถทำให้แอปพลิเคชันของคุณคลายการบีบอัดสตรีม Brotli ที่สร้างขึ้นเป็นพิเศษได้ จะสามารถทำให้หน่วยความจำของโปรเซสเสียหาย ซึ่งอาจนำไปสู่:
- การแครช (denial of service) ซึ่งเป็นผลลัพธ์ที่ผู้โจมตีทำให้เกิดได้อย่างแน่นอนที่สุด
- การรั่วไหลของหน่วยความจำโปรเซส response หรือ log อาจเปิดเผยบางส่วนของ secret, token หรือข้อมูลของผู้ใช้รายอื่น
- อาจเกิดการรันโค้ดจากระยะไกล Node.js ระบุว่า RCE เป็นผลกระทบที่อาจเกิดขึ้นได้ [2] proof of concept สาธารณะตัวแรกสามารถรันโค้ดได้เฉพาะกับบิลด์ที่ถูกจงใจทำให้อ่อนแอลงเท่านั้น แต่ต่อมานักวิจัยได้รายงานว่าสามารถรันโค้ดได้ แม้จะยังไม่เสถียร บนบิลด์ Node.js 24.22.0 อย่างเป็นทางการที่ไม่ได้ถูกดัดแปลง [3]
ไม่จำเป็นต้องยืนยันตัวตน: ผู้โจมตีเพียงแค่ส่งไบต์ให้ไปถึงตัวถอดรหัสได้ นี่คือเหตุผลที่คะแนน CVSS 4.0 อยู่ที่ 9.2 (Critical) [1] ดังนั้นคำถามสำคัญสำหรับทุกระบบจึงไม่ใช่ “เราใช้ Brotli หรือไม่” แต่คือ “ฝ่ายที่ไม่น่าเชื่อถือสามารถทำให้เราคลายการบีบอัด Brotli ได้หรือไม่”
กรณีการใช้งานทั่วไปและความเสี่ยง
กรณีที่ 1: API ที่เปิดสู่อินเทอร์เน็ตซึ่งรับ request body แบบบีบอัด (ลำดับความสำคัญสูงสุด)
เซิร์ฟเวอร์ API ที่ใช้ Node.js, BFF, API gateway และ endpoint สำหรับอัปโหลดบางตัวคลายการบีบอัด request body ที่ส่งมาพร้อม Content-Encoding: br ส่วนบางตัวทำเช่นเดียวกันผ่าน middleware ความเสี่ยง: ไคลเอนต์นิรนามใดก็ได้บนอินเทอร์เน็ตสามารถส่ง body ที่สร้างขึ้นเป็นพิเศษได้ ผลกระทบมีตั้งแต่ทำให้บริการแครชซ้ำ ๆ ซึ่งเป็น DoS ที่ทำได้ด้วยต้นทุนต่ำ ไปจนถึงการรั่วไหลของหน่วยความจำจากโปรเซสที่เก็บข้อมูลเซสชันและ API key ความเร่งด่วน: ฉุกเฉิน แพตช์ภายในวันนี้ และบล็อก request body แบบ br ที่ขอบเครือข่าย (edge) จนกว่าจะแพตช์เสร็จ
กรณีที่ 2: บริการที่ดึงเนื้อหาจากภายนอก (ลำดับความสำคัญสูง)
ตัวรับ webhook, crawler และ scraper, บริการพรีวิวลิงก์และ RSS, การเชื่อมต่อระบบชำระเงินหรือ SaaS และ AI agent ที่ท่องเว็บ ล้วนส่ง HTTP request ออกไปภายนอก HTTP client จำนวนมากส่ง Accept-Encoding: br และคลายการบีบอัด response โดยอัตโนมัติ ใน Python นั้น urllib3 และ requests จะทำเช่นนี้ทุกครั้งที่มีการติดตั้งแพ็กเกจ Brotli หรือ brotlicffi แม้โค้ดของคุณจะไม่เคย import แพ็กเกจนั้นเลยก็ตาม aiohttp ก็ทำเช่นเดียวกัน และ httpx จะทำเช่นนี้เมื่อติดตั้งพร้อม extra brotli [4] ความเสี่ยง: เซิร์ฟเวอร์ปลายทางที่เป็นอันตราย ถูกเจาะระบบ หรือถูกปลอมแปลง สามารถโจมตี backend ของคุณผ่าน response ของมันได้ ผู้โจมตีไม่จำเป็นต้องเข้าถึงเครือข่ายของคุณเลย เพราะคุณเป็นฝ่ายเรียกไปหาเขาเอง ความเร่งด่วน: สูง ให้แพตช์ก่อนในจุดที่ปลายทางไม่น่าเชื่อถืออย่างสมบูรณ์
กรณีที่ 3: แอปเดสก์ท็อป AI coding agent และ CLI ที่มี runtime ฝังอยู่
แอป Electron, CLI ที่สร้างบน Bun หรือ Node และเครื่องมือ AI สำหรับนักพัฒนา มี runtime สำเนาของตัวเองติดมาด้วย การอัปเดตแพ็กเกจ node ของระบบจึงไม่ได้แก้ปัญหาในเครื่องมือเหล่านี้ การอัปเดตแอปบนดิสก์ก็ไม่ได้แก้ปัญหาในสำเนาที่กำลังรันอยู่เช่นกัน เพราะโปรเซสที่รันต่อเนื่องเป็นเวลานานยังคงเก็บ runtime ตัวเก่าไว้ในหน่วยความจำจนกว่าจะถูกรีสตาร์ท ความเสี่ยง: เครื่องมือเหล่านี้มักถือ credential และดึงเนื้อหาจากภายนอก ซึ่งเท่ากับเป็นกรณีที่ 2 ที่รวมกับโปรเซสที่มีสิทธิ์สูง ความเร่งด่วน: สูงสำหรับเครื่องมือที่ดึงเนื้อหาที่ไม่น่าเชื่อถือ ให้อัปเดต แล้วรีสตาร์ทจริง ๆ เราได้อธิบายกับดัก “อัปเดตแล้วแต่ยังรันโค้ดเก่าอยู่” อย่างละเอียดไว้ในบทความ HTTP2Shell: ทำไมการอัปเดตไบนารีจึงไม่ได้แก้ไขโปรเซสที่กำลังรันอยู่
กรณีที่ 4: container image และ artifact ของ CI/CD
image ที่บิลด์ FROM node:22, node:24 หรือ node:26 ก่อนจะมีการแก้ไข ยังคงมี runtime ที่มีช่องโหว่อยู่ แม้ว่าโฮสต์จะได้รับการแพตช์แล้วก็ตาม เช่นเดียวกับ Python wheel ที่รวมมาด้วยและ dependency ที่ vendor ไว้ ความเสี่ยง: โค้ดที่มีช่องโหว่จะกลับมาทุกครั้งที่ deploy และทุกครั้งที่เกิด autoscaling จนกว่าจะบิลด์ image ใหม่ ความเร่งด่วน: สูงสำหรับ image ที่อยู่เบื้องหลังกรณีที่ 1 และ 2 ให้บิลด์ใหม่ แทนที่จะแค่รีสตาร์ท
กรณีที่ 5: ไลบรารีระบบของ Linux ฟอนต์ และการประมวลผลภาพ
ดิสทริบิวชันต่าง ๆ จัดส่งตัวถอดรหัสในรูปแบบ shared library เช่น libbrotli1 บน Ubuntu/Debian ซึ่งถูกใช้โดย curl และ libcurl เมื่อเปิดใช้การบีบอัด ใช้โดย FreeType สำหรับเว็บฟอนต์ WOFF2 และถูกใช้ทางอ้อมโดยเครื่องมือประมวลผลภาพและเอกสาร เช่น Pillow ความเสี่ยง: ระบบที่เรนเดอร์ฟอนต์หรือเอกสารที่ผู้ใช้อัปโหลด หรือดึงเนื้อหาภายนอกด้วย curl --compressed อาจถูกข้อมูล Brotli ที่ไม่น่าเชื่อถือเข้าถึงได้ เซิร์ฟเวอร์ที่ไม่เคยป้อนข้อมูลภายนอกเข้าสู่ไลบรารีเหล่านี้มีความเสี่ยงในทางปฏิบัติต่ำ ความเร่งด่วน: ปานกลางในกรณีส่วนใหญ่ แต่สูงสำหรับบริการเรนเดอร์เอกสารหรือประมวลผลไฟล์อัปโหลด Ubuntu ได้เผยแพร่แพ็กเกจ brotli ที่แก้ไขแล้วสำหรับ 22.04, 24.04, 26.04 และ 26.10 [1] สำหรับ RHEL, Oracle Linux และดิสทริบิวชันอื่น ๆ ให้ตรวจสอบประกาศด้านความปลอดภัยของผู้จำหน่ายสำหรับแพ็กเกจ brotli แทนที่จะคาดเดาสถานะเอาเอง
กรณีที่ 6: ระบบภายในที่รับเฉพาะอินพุตที่เชื่อถือได้ (ลำดับความสำคัญต่ำกว่า)
บริการบางตัวคลายการบีบอัด Brotli เฉพาะข้อมูลที่คุณสร้างขึ้นเอง เช่น แคชภายในหรือ build artifact ของคุณเอง ระบบเหล่านี้มีความเสี่ยงต่ำกว่า แต่ไม่ใช่ศูนย์ เพราะผู้โจมตีที่มีจุดยึดในระบบอยู่แล้วสามารถใช้บั๊กนี้เพื่อเคลื่อนที่ต่อไปได้ ความเร่งด่วน: แพตช์ในรอบอัปเดตตามปกติครั้งถัดไป
สิ่งที่ต้องทำ: ขั้นตอนการรับมือ
ขั้นตอนที่ 1: ค้นหาจุดที่มีการถอดรหัส Brotli (ภายในวันนี้)
- Node.js: ตรวจสอบ
node -vบนทุกโฮสต์ รวมถึงในทุก container image และ CI runner ค้นหาในโค้ดและคอนฟิกเพื่อหาbrotliDecompress,createBrotliDecompressและ middleware สำหรับ parse body ที่คลายการบีบอัดbr - runtime ที่ฝังอยู่: ทำรายการแอป Electron, CLI ของ Bun/Node และ AI agent ที่ใช้งานอยู่ และบันทึกเวอร์ชัน runtime ที่แต่ละตัวฝังไว้ ไม่ใช่แค่เวอร์ชันของแอป
- Python: รัน
pip show Brotli brotlicffiในทุก environment และ image มองหาhttpx[brotli]และ dependency ทางอ้อม (transitive) ใน lockfile และ SBOM - แพ็กเกจของ OS:
dpkg -l | grep brotliหรือrpm -qa | grep brotliจากนั้นดูว่าโปรเซสใดโหลดไลบรารีนี้อยู่จริง - จัดลำดับความสำคัญ ตามกรณีข้างต้น: สิ่งใดก็ตามที่อินพุตที่ไม่น่าเชื่อถือเข้าถึงได้ (กรณีที่ 1, 2, 3 และ 5 ที่มีการอัปโหลด) ต้องมาก่อน
ขั้นตอนที่ 2: แพตช์คอมโพเนนต์ที่ได้รับผลกระทบ
- Node.js: อัปเกรดเป็น 22.23.4, 24.22.1 หรือ 26.12.1 หรือใหม่กว่า [2]
- Python:
Brotli>=1.2.1หรือbrotlicffi>=1.2.1.0และสร้าง lockfile ใหม่ [4] - Brotli ต้นทาง (upstream) / โค้ด C ที่ vendor ไว้: 1.0.10, 1.1.1 หรือ 1.2.1 ขึ้นอยู่กับ branch [1]
- แพ็กเกจของ OS: ติดตั้งอัปเดตความปลอดภัยของดิสทริบิวชันที่คุณใช้สำหรับ
brotli/libbrotli - แอปเดสก์ท็อปและ agent: อัปเดตเป็นรีลีสของผู้จำหน่ายที่ระบุว่ามี runtime ที่แก้ไขแล้ว หากผู้จำหน่ายยังไม่ได้เผยแพร่ข้อมูลใด ๆ ให้ถือว่าแอปนั้นยังไม่ได้รับการยืนยัน ไม่ใช่ว่าปลอดภัย
ขั้นตอนที่ 3: บิลด์ใหม่ deploy ใหม่ และรีสตาร์ท
- บิลด์ container image ใหม่จาก base image ที่แพตช์แล้ว แล้ว deploy ใหม่ การรีสตาร์ท image เก่าไม่ช่วยอะไร
- รีสตาร์ททุกโปรเซสที่รันต่อเนื่องเป็นเวลานานซึ่งโหลดไลบรารีที่มีช่องโหว่ไว้: บริการ Node, worker, เซสชันของ agent และทุกอย่างที่ลิงก์กับไลบรารีระบบ สำหรับงานที่มีสถานะ (stateful) และ AI agent ให้ drain หรือส่งต่องานก่อน เพื่อไม่ให้อีเวนต์ที่อยู่ในคิวหรือรายการอนุมัติสูญหาย
ขั้นตอนที่ 4: ลดความเสี่ยงระหว่างแพตช์
- ขาเข้า: ปฏิเสธ request body ที่
Content-Encodingมีbrที่ reverse proxy, load balancer หรือ WAF ก่อนที่ตัวถอดรหัสใด ๆ จะได้รับข้อมูล - ขาออก: การลบ
brออกจากAccept-Encodingเพียงอย่างเดียวไม่เพียงพอ เพราะเซิร์ฟเวอร์ที่เป็นอันตรายยังคงส่งbrมาได้อยู่ดี ให้ปฏิเสธหรือไม่ถอดรหัส response ที่มาพร้อมContent-Encoding: brด้วย [4] - ทางเลือกสำรองสำหรับ Python: ในจุดที่ยังอัปเกรดไม่ได้ ให้ถอนการติดตั้ง
Brotliและbrotlicffiเพื่อให้ไคลเอนต์หยุดถอดรหัสbrโดยให้ทดสอบก่อน เพราะเซิร์ฟเวอร์บางตัวจะยังคงส่งbrมา
ขั้นตอนที่ 5: ตรวจสอบยืนยัน และเฝ้าระวังสัญญาณการโจมตี
- ยืนยันเวอร์ชัน runtime จากภายในโปรเซสหรือ container ที่กำลังรันอยู่ ไม่ใช่จาก package manager เพียงอย่างเดียว
- สแกน image และ SBOM ใหม่ เพื่อให้แน่ใจว่าไม่มีสำเนาเวอร์ชันเก่าที่ยังถูกดึงเข้ามาทางอ้อม
- ตรวจสอบ log ล่าสุดเพื่อหาการแครชที่ไม่ทราบสาเหตุ segmentation fault หรือการรีสตาร์ทวนซ้ำในบริการที่จัดการ
brการแครชจำนวนมากจากแหล่งเดียวกันควรได้รับการตรวจสอบในฐานะความพยายามโจมตี - หากบริการที่มีความเสี่ยงสูงแครชโดยไม่คาดคิดก่อนได้รับการแพตช์ ให้พิจารณาเปลี่ยน (rotate) secret ที่โปรเซสนั้นถือไว้ เนื่องจากไม่สามารถตัดความเป็นไปได้ที่หน่วยความจำจะรั่วไหล
สรุป
| สถานการณ์ | ความเสี่ยง | สิ่งที่ต้องทำ |
|---|---|---|
API สาธารณะถอดรหัส request body แบบ br | วิกฤต | แพตช์ทันที; บล็อก br ที่ edge |
| Backend ดึง URL, webhook หรือหน้าเว็บภายนอก | สูง | แพตช์ทันที; ปฏิเสธ response แบบ br |
| แอป Electron, AI agent หรือ CLI ที่มี runtime ฝังอยู่ | สูง | อัปเดตและรีสตาร์ททุกอินสแตนซ์ที่กำลังรัน |
| container image และ artifact ของ CI ที่เก่า | สูง | บิลด์ใหม่จาก base image ที่แพตช์แล้วและ deploy ใหม่ |
ไลบรารีระบบที่ใช้กับไฟล์อัปโหลด ฟอนต์ หรือ curl --compressed | ปานกลาง–สูง | ติดตั้งอัปเดตของ OS; รีสตาร์ทบริการที่โหลดไลบรารีนี้ |
| เฉพาะข้อมูลภายในที่เชื่อถือได้ | ต่ำ–ปานกลาง | แพตช์ในรอบถัดไป |
การแพตช์แพ็กเกจเป็นเพียงครึ่งหนึ่งของงาน ความเสี่ยงจะหมดไปก็ต่อเมื่อไม่มีโปรเซสที่กำลังรัน image หรือ runtime ที่ฝังอยู่ใด ๆ ที่ยังถอดรหัสข้อมูล Brotli ที่ไม่น่าเชื่อถือด้วยโค้ดเก่าได้
Global
Japan
Korea
China
Taiwan
Vietnam
Indonesia
Portugal
Spain
France
Germany
Egypt
Russia