มันคืออะไร?
CVE-2025-59057
- ความรุนแรง: High (CVSS ~7.6)
- ประเภท: Cross-Site Scripting (XSS)
- เป้าหมาย: แอปพลิเคชันที่รันใน Framework Mode (Server-Side Rendering)
ปัญหาเกิดที่ฟังก์ชัน meta() หรือ <Meta> component เวลาที่เราพยายามจะทำ Structured Data (JSON-LD) เพื่อเอาใจ Google ครับ ปกติเราจะใส่ script เข้าไปแบบนี้:
{
"script:ld+json": {
"@context": "https://schema.org",
"@type": "Product",
"name": data.productName
}
}วิธีการโจมตี
ลองจินตนาการว่าเราทำหน้าสินค้า แล้วรับชื่อสินค้าจาก URL มาแสดงใน Meta Tag ตรงๆ แฮกเกอร์จะส่งลิงก์หน้าเว็บเราให้เหยื่อ โดยแก้ URL เป็น Payload หน้าตาประมาณนี้:
Payload:
my-product"</script><script>alert('HACKED')</script>```
เมื่อ Server ทำการ Render HTML ส่งกลับมาที่ Browser แทนที่มันจะเป็น JSON ปกติ มันจะกลายเป็นแบบนี้:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "my-product"
}
</script> <script>alert('HACKED')</script>
"}
</script>ผลลัพธ์: ทันทีที่ผู้ใช้กดลิงก์ Script ของแฮกเกอร์จะทำงานทันที (ขโมย Cookie, Redirect เว็บ, หรือหลอกถามรหัสผ่าน)
ทำไมถึงเกิดขึ้นได้
ปกติเวลาเราเขียน JSON-LD ใน React เรา ไม่ต้องใส่
<script>
เอง ครับ
เราเขียนแค่ Object ธรรมดาแบบนี้:
// ใน React Router
{
"script:ld+json": { // Key พิเศษ บอก Framework ว่านี่คือ JSON-LD นะ
"@context": "https://schema.org",
"name": "My Page"
}
}และ React Router จะเป็นคน "สร้าง Tag <script>
ครอบให้เรา" ตอนมันแปลงเป็น HTML ครับ สิ่งที่ส่งไป Browser คือ:
<script type="application/ld+json">
{"@context":"...","name":"My Page"}
</script>React Router สร้าง Tag เปิด:
```<script type="application/ld+json">```
React Router เอา JSON ของเรามาวาง:
``` {"name": "</script><script>alert()"}```
React Router สร้าง Tag ปิด:
</script>
<script type="application/ld+json">
{"name": "
</script> <!-- Tag ปิดที่ 1 (User ใส่มา) -->
<script>alert()</script> <!-- Script ปลอม (User ใส่มา) -->
"}
</script> <!-- Tag ปิดที่ 2 (ที่ Framework สร้างให้ แต่ไม่มีคู่แล้ว) -->ใครบ้างที่งานเข้า?
เช็ค package.json ของคุณด่วนครับ ถ้าใช้เวอร์ชันในช่วงนี้ "โดนหมด":
- react-router: ตั้งแต่ v7.0.0 ถึง v7.8.2
- @remix-run/react: ตั้งแต่ v1.15.0 ถึง v2.17.0
หมายเหตุ: คนที่ใช้แค่ Client-side Routing (SPA) ทั่วไปจะไม่ได้รับผลกระทบ จะโดนเฉพาะคนที่ใช้ Framework Mode (SSR) ครับ
ทางแก้ จากทีมงาน react-router
ทีมงาน React Router รับทราบและปล่อยแพทช์แก้มาแล้วเมื่อไม่กี่วันที่ผ่านมา (มกราคม 2026) วิธีแก้คือการอัปเดตให้เวอร์ชันใหม่กว่าช่วงที่มีปัญหา:
# สำหรับ React Router v7
npm install react-router@latest
# สำหรับ Remix
npm install @remix-run/react@latestเวอร์ชันที่ปลอดภัย:
- react-router: v7.9.0 ขึ้นไป
- @remix-run/react: v2.17.1 ขึ้นไป
ทางแก้แบบ manual ไปก่อน
ทำการติดตั้ง lib "jsesc" https://www.npmjs.com/package/jsesc
แล้วทำการ sanitize name ออก. ถ้าทำมือน่าจะต้องเขียน replace เยอะอยู่แต่ถ้า ใช้ jsesc จะช่วยลดเวลาส่วนนั้นลงเยอะและ code จะดู clean ขึ้น
import jsesc from "jsesc";
const sanitizeInputUrl = (str: string | undefined) => {
if (!str) return "";
return jsesc(str, { isScriptContext: true });
}
// ทำการเรียกใช้ sanitize ก่อน return กลับไปให้ payload
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [
{ title: "Vulnerable Page" },
{
"script:ld+json": {
"@context": "https://schema.org",
"@type": "Thing",
"name": sanitizeInputUrl(data?.name),
},
},
];
};
บทสรุป
เรื่องนี้สอนให้รู้ว่า "อย่าไว้ใจ Input ไหนเลย แม้กระทั่งใน Meta Tag" ปกติเราจะระวัง XSS กันแค่ใน <body> หรือจุดที่ render เนื้อหา แต่จุดเล็กๆ อย่าง SEO Tag ก็เป็นช่องโหว่ให้โดนเล่นงานได้เหมือนกัน
รีบไปเช็คโปรเจกต์ของลูกค้าหรือของตัวเอง แล้วอัปเดตด่วนครับ กันไว้ดีกว่าแก้!
#ReactRouter #Security #CVE2025 #WebDevelopment #Frontend #SandwichedDeveloper


