- React และ Next.js รายงานพบช่องโหว่ความปลอดภัยที่ทำให้เกิด RCE (Remote Code Execution) ได้
- ปัญหานี้เกิดขึ้นภายใน แพ็กเกจ Next.js โดยผู้โจมตีสามารถใช้ข้อมูลที่เป็นอันตรายเพื่อกระตุ้นให้เกิดการ รันโค้ดตามอำเภอใจ ได้
- Vercel เปิดเผยช่องโหว่นี้ผ่าน คำแนะนำด้านความปลอดภัยของ GitHub (GHSA-9qr9-h5gf-34mp) และเผยแพร่ เวอร์ชันอัปเดต
- ผู้ใช้ควรอัปเกรดเป็น เวอร์ชันล่าสุด เพื่อบรรเทาช่องโหว่
- กรณีนี้ย้ำย้ำถึงความสำคัญของการควบคุมความปลอดภัยในระดับเฟรมเวิร์กอีกครั้ง
ภาพรวมช่องโหว่ RCE
- พบช่องโหว่ที่ทำให้เกิดการรันโค้ดระยะไกลได้ในสภาพแวดล้อม Next.js และ React
- มีความเสี่ยงที่ผู้โจมตีจะสามารถรัน โค้ด JavaScript ตามอำเภอใจ บนฝั่งเซิร์ฟเวอร์ได้
- ช่องโหว่นี้เกิดจากกระบวนการประมวลผลโค้ดภายใน แพ็กเกจ Next.js
- รายละเอียดเชิงลึกของฟังก์ชันหรือโมดูลที่มีช่องโหว่ยังไม่ถูกเปิดเผย
ผลกระทบและการตอบสนอง
- Vercel ประกาศปัญหานี้อย่างเป็นทางการผ่าน GitHub Security Advisory (GHSA-9qr9-h5gf-34mp)
- คำแนะนำดังกล่าวถูกโพสต์ในส่วนประกาศความปลอดภัยของ คลังโค้ด Next.js
- เวอร์ชันที่มีช่องโหว่ไม่ได้ระบุไว้ชัดเจน แต่มีการ จัดแพ็กเกจเวอร์ชันอัปเดต
- แนะนำให้ผู้ใช้ อัปเกรดเป็นเวอร์ชันเสถียรล่าสุด
คำแนะนำด้านความปลอดภัยและการดำเนินการ
- โครงการทุกประเภทที่ใช้ แพ็กเกจ Next.js ควรตรวจสอบเวอร์ชันทันที
- ต้องคงเวอร์ชัน Next.js ใน
package.json ให้อยู่ในสถานะล่าสุด
- Vercel ไม่มีการระบุการบรรเทาเพิ่มเติมนอกเหนือจากการส่งมอบเวอร์ชันที่แก้ไขแล้ว
- รายละเอียดทางเทคนิคที่ละเอียดของช่องโหว่ยังอยู่ในสถานะ ไม่เปิดเผย โดยให้ข้อมูลเฉพาะเท่าที่จำเป็นเพื่อเหตุผลด้านความปลอดภัย
ความสำคัญ
- ช่องโหว่นี้แสดงให้เห็นความเสี่ยงของการรันโค้ดในสภาพแวดล้อมการเรนเดอร์ฝั่งเซิร์ฟเวอร์
- ผู้ดูแลบริการที่อิง React และ Next.js ควรอัปเดตความปลอดภัยเป็นประจำ
- ช่องโหว่ด้านความปลอดภัยในระดับเฟรมเวิร์กสามารถส่งผลโดยตรงต่อความปลอดภัยของ ระบบแอปพลิเคชันทั้งหมด
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ช่องโหว่นี้เป็นกรณีที่ สถานการณ์เลวร้ายที่สุด ที่มีการเตือนกันมาตั้งแต่ตอนนำ RSC/server actions เข้ามาใช้งาน กลายเป็นความจริง
เซิร์ฟเวอร์ทำการ deserialize อินพุตที่ไม่น่าเชื่อถือจากไคลเอนต์ตรงๆ แล้วค้นหาโมดูลกับชื่อ export เพื่อรัน
แม้จะกันได้ด้วยแพตช์
hasOwnPropertyแต่ปัญหาที่แท้จริงคือไม่ได้ตระหนักอย่างชัดเจนว่า React กำลังสร้าง RPC layer ขึ้นมาเฟรมเวิร์ก RPC แบบดั้งเดิมอย่าง gRPC หรือ SOAP กำหนดขอบเขตให้ชัดด้วยสคีมาและ service definition แบบ explicit แต่ React อันตรายกว่าเพราะเป็นแนวทางที่เปิดเผย API ทุกตัวที่ bundler มองเห็นได้
ปัญหาด้านความปลอดภัยจากการออกแบบแบบนี้มีแนวโน้มจะเกิดซ้ำอีกในอนาคต
ต่อให้มี explicit schema ถ้าขั้นตอนสุดท้ายยังปล่อยให้อินพุตที่ไม่น่าเชื่อถืออ้างถึง object ใดก็ได้ใน namespace ของเซิร์ฟเวอร์ ก็ไม่มีประโยชน์
จะเปิดเผยเฉพาะฟังก์ชันที่ทำเครื่องหมายด้วย
"use server"เท่านั้น และทีม React ก็รับรู้ว่าตัวเองกำลังออกแบบระบบ RPC อยู่บั๊กแบบนี้สามารถเกิดขึ้นได้กับระบบ RPC อื่นๆ เช่นกัน (ผู้แสดงความคิดเห็นเป็นผู้มีส่วนร่วมใน React)
แต่การคง private repo เก่าๆ ไว้ต่อไปก็ไม่ใช่ตัวเลือกที่ดีเช่นกัน
Next มีข้อดีจริงๆ แค่อย่างเดียวคือ static build
ถ้าหยุดรองรับเมื่อไร ก็ไม่มีเหตุผลให้ใช้อีกต่อไป
ตาม ประกาศเตือนด้านความปลอดภัย ของ Facebook/Meta, React Server Components เวอร์ชัน 19.0.0~19.2.0 มีช่องโหว่ Remote Code Execution (RCE) ก่อนการยืนยันตัวตน
ใน ประกาศ บนบล็อกทางการของ React ก็อธิบายว่า เนื่องจากโครงสร้างที่ไคลเอนต์สามารถเรียก server function ได้ ผู้โจมตีจึงอาจสร้าง HTTP request ที่เป็นอันตรายเพื่อรันโค้ดตามอำเภอใจบนเซิร์ฟเวอร์ได้
hasOwnPropertyการโจมตีก็น่าจะเป็นการอ้างถึงพร็อพเพอร์ตีใน prototype chain (__proto__เป็นต้น)คอมมิตที่แก้ไขน่าจะเป็น คอมมิตนี้
ดูเหมือนว่าจะถูก squash รวมกับการเปลี่ยนแปลงหลายอย่าง เลยทำให้รายละเอียดถูกกลบไป
ในโค้ดเห็นแพตเทิร์นการจำกัดรายชื่อฟังก์ชันที่เปิดเผยแบบ whitelist อยู่ 4 จุด
Vercel มีการบล็อกรูปแบบ request อันตรายไว้แล้วที่ ระดับแพลตฟอร์ม
ดู ประกาศ
ฝั่ง Cloudflare ก็รับมือเชิงรุกด้วย กฎ WAF
ถึงอย่างนั้นก็ยังแนะนำอย่างยิ่งให้อัปเดต dependency ของ Next, React และ meta framework อื่นๆ ทันที
บทความบล็อก ของ Deno Deploy/Subhosting ก็น่าอ่านเช่นกัน
ลองอ้างอิง PoC repository เพื่อทดสอบจำลองช่องโหว่นี้ดูแล้ว
react-server-dom-webpackที่แพตช์แล้วก็ยังรัน RCE ได้ เลยดูเหมือนว่ากลไกอาจยังไม่ตรงทั้งหมดถ้ามีเดโมบนโปรเจกต์ Next.js จริงก็น่าจะดี
ถึงขั้นมีคำพูดว่า “ไม่มี Vercel ก็ไม่มี RCE” ซึ่งสะท้อนให้เห็นว่าเหตุการณ์นี้เผยให้เห็น ความสัมพันธ์ระหว่างสภาพแวดล้อมโฮสต์กับความปลอดภัย
คะแนน CVE 10.0 เป็นตัวเลขที่ น่าตกใจ สำหรับโปรเจกต์ที่ถูกใช้อย่างแพร่หลายแบบนี้
แต่ถึงอย่างนั้นก็ยังมียอดดาวน์โหลดต่อสัปดาห์เกิน 310,000 ครั้ง
เข้าใจได้ยากว่าทำไมทีม React ถึงใช้เวลากับฟีเจอร์ที่ ชวนสับสน แบบนี้
ก็ยังสงสัยว่ามันดีกว่า SSR อย่างไร และช่วยเรื่องประสิทธิภาพได้มากแค่ไหน
หลังมีการนำ Hook เข้ามา ประสบการณ์นักพัฒนาก็แย่ลง แต่แทนที่จะปรับปรุงจุดนั้นกลับเพิ่มความซับซ้อนแบบใหม่เข้ามาอีก
ถ้าเป็นไปได้อยากให้ทำให้สามารถใช้ control flow ตามธรรมชาติของ JS ใน component logic ได้อย่างเป็นธรรมชาติมากกว่า
ฉันมองมันเป็นชั้น BFF (Backend for Frontend) แบบทำให้เป็น component
แต่ละชิ้นของ UI เชื่อมตรงกับ backend logic ที่สอดคล้องกัน ทำให้ดึงข้อมูลได้โดยไม่ต้องเรียก
fetchแบบนี้ช่วยให้ฝั่ง frontend และ backend พัฒนาไปด้วยกันได้ง่ายขึ้น และโหลดเฉพาะข้อมูลที่จำเป็นได้ละเอียดขึ้น
สุดท้ายคือสามารถฝัง server logic ที่มีไว้เพื่อ UI โดยเฉพาะ เข้าไปในโครงสร้าง component ได้อย่างเป็นธรรมชาติ
โมเดลแบบ compiler-based ของ Svelte หรือ React ใช้งานง่ายกว่ามาก
Vue, Svelte, Angular ฯลฯ ต่างก็ต้องใช้ compiler และ file extension แยกต่างหาก
ในขณะที่ React/JSX ได้รับสิทธิพิเศษตั้งแต่ขั้น preprocessor ไปแล้ว
Rust แก้ปัญหาแบบนี้ด้วยระบบ macro — ตัวอย่างเช่น Leptos และ Yew รองรับ JSX หรือ HTML template ภายในไฟล์
.rsมาตรฐานได้ถ้า JS ยังไม่มีความสามารถในการขยายแบบนี้ เว็บก็คงมีแนวโน้มจะยังเป็น สภาพแวดล้อมที่ซับซ้อนและไร้ประสิทธิภาพ ต่อไป
พยายามลดภาระฝั่งไคลเอนต์ แต่ก็ให้ความรู้สึกว่าแม้แต่จุดนั้นก็ยังไม่สำเร็จ
คำอธิบายแบบละเอียด บนบล็อก React ก็น่าอ่านเช่นกัน