Laravel TokenGuard ข้ามล็อกอินได้ CVE-2026-114509 รวม Livewire Filament
ใครรัน Laravel 12 หรือ 13 ที่ใช้ guard แบบ token กับ MySQL หรือ MariaDB ให้อัปเดตเป็น 12.69.0 หรือ 13.30.0 ก่อน ส่วน Livewire 4.x ที่ใช้ #[Authorize] กับ Filament 4/5 ที่เปิด MFA ให้อัปเดตตามมา
สรุปใน 1 นาที
- อาการ/ปัญหา
- TokenGuard ของ Laravel รับค่า credential ที่ไม่ใช่ string แล้วจับคู่ผิดคน ทำให้ล็อกอินเป็นผู้ใช้อื่นได้โดยไม่รู้ token ในบางการตั้งค่า MySQL หรือ MariaDB
- ใครควรอ่าน
- แอป Laravel 12 ก่อน 12.68.0 และ 13 ก่อน 13.29.0 ที่ใช้ guard แบบ token ส่วน advisory อื่นกระทบเฉพาะแอปที่ใช้ Livewire, Filament, league/commonmark ตามช่วงรุ่นในตาราง
- ทางแก้แบบสั้น
- composer update laravel/framework livewire/livewire filament/filament league/commonmark symfony/http-foundation phpseclib/phpseclib --with-dependencies แล้วรีสตาร์ต worker และเช็ก APP_DEBUG=false
พอดีเห็น Packagist ขึ้น security advisory ของระบบนิเวศ Laravel ออกมาเป็นชุดช่วง 23 ต.ค. 2026 ผมเลยไล่เปิดหน้า advisory ของ GitHub ทีละตัวแทนที่จะอ่านจากข่าว เพราะหลายตัวมีเงื่อนไขเฉพาะ (ต้องใช้ฟีเจอร์นั้น ต้องเปิด debug ต้องเป็นฐานข้อมูลแบบนั้น) และถ้าอ่านแค่หัวข้อจะประเมินผิดได้ง่าย บันทึกนี้รวมเฉพาะที่ผมเปิดอ่านต้นฉบับครบแล้ว จัดเป็นกลุ่มตามแพ็กเกจ
ตัวที่ต้องดูก่อนคือ laravel/framework เรื่อง TokenGuard ที่ได้ระดับ Critical ตัวอื่นส่วนใหญ่เป็นระดับกลางถึงต่ำ และทุกตัวมีรุ่นแก้ออกมาแล้ว
เกิดอะไรขึ้น
TokenGuard (CVE-2026-114509) เป็นตัวหลักของรอบนี้ ถ้า guard แบบ token มาตรฐานของ Laravel ได้รับ credential ที่ไม่ใช่ string ตามที่ผู้โจมตีสร้างมาเฉพาะ ในบางการตั้งค่าของ MySQL หรือ MariaDB ค่านั้นถูกจัดการผิดในขั้นค้นหาผู้ใช้ คำสั่ง query เลยไปจับคู่กับ record ของผู้ใช้อีกคน ผลคือคนที่ไม่ต้องล็อกอินเข้าระบบเป็นผู้ใช้ที่มีอยู่จริงอีกคนได้ โดยไม่รู้ API token ของคนนั้น และเข้าได้ทุก route ที่ guard ตัวนี้คุมอยู่ advisory ไม่ได้บอกว่าการตั้งค่าฐานข้อมูลแบบไหนที่ทำให้เกิดผล และหน้านั้นก็ไม่เอ่ยถึง Sanctum หรือ Passport เลย ผมเลยไม่ขอเดาว่าตัวไหนโดนหรือไม่โดน
ไม่ต้องมีบัญชี ไม่ต้องรู้ token ต่อให้ route มี middleware auth ครบ ถ้า guard เป็นตัวที่โดน ก็ถูกข้ามได้ ข้อควรจำคือ advisory ไม่ประกาศ workaround ทางแก้ที่เห็นคืออัปเดตเป็น 12.68.0 หรือ 13.29.0 ขึ้นไป
อีกสองตัวใน laravel/framework
- Relationship inclusion (CVE-2026-114508) ที่ endpoint อ่านข้อมูลบางแบบ request ที่ประกอบมาเฉพาะทำให้เกิดคำสั่งลบข้อมูลในตารางที่เกี่ยวข้อง ทั้งที่ผู้เรียกมีสิทธิ์แค่อ่าน advisory เตือนว่าข้อมูลที่หายกู้คืนไม่ได้ เช่นตารางที่ผูกกันถูกล้างทั้งตาราง
- Debug page XSS (CVE-2026-102279) เกิดเมื่อ
APP_DEBUG=trueเท่านั้น ข้อมูลที่ผู้โจมตีคุมได้ไปอยู่ใน tooltip ของ Tippy.js ที่เปิดallowHTMLและทำงานตอนเอาเมาส์ไปชี้
ฝั่ง Livewire, Filament และไลบรารีอื่นแต่ละตัวเล็กกว่านี้ ผมรวมไว้ในหัวข้อถัดไป
ระดับความรุนแรง
| แพ็กเกจ | ตัวระบุ | ระดับ | CVSS |
|---|---|---|---|
| laravel/framework TokenGuard | CVE-2026-114509 | Critical | 9.2 (v4) |
| laravel/framework relationship | CVE-2026-114508 | Moderate | 6.5 (v3.1) |
| laravel/framework debug page | CVE-2026-102279 | Low | 3.1 (v3.1) |
livewire #[Authorize] |
GHSA-mhf7-xp6r-6qrc (ไม่มี CVE) | Moderate | 6.5 (v3.1) |
| livewire DOM XSS | CVE-2026-81887 | Moderate | 5.1 (v4) |
| filament MFA bypass เมื่อเปิด recovery codes | CVE-2026-77567 | High | 8.1 (v3.1) |
| filament MFA รหัสเก่าใช้ซ้ำได้ | CVE-2026-84306 | Moderate | 6.5 (v3.1) |
| filament password validity รั่ว | CVE-2026-84307 | Low | 3.7 (v3.1) |
| filament MFA ไม่ถามรหัสผ่านซ้ำ | CVE-2026-104181 | Moderate | 5.4 (v3.1) |
| phpseclib X25519 | CVE-2026-84308 | Moderate | 6.3 (v3.1) |
| symfony/http-foundation ReDoS | CVE-2026-108082 | High (GitHub) | 8.7 (v4) |
เวกเตอร์ TokenGuard คือเรียกผ่านเครือข่าย ซับซ้อนต่ำ ไม่ต้องมีสิทธิ์ ไม่ต้องให้ใครคลิก และกระทบ confidentiality, integrity, availability ระดับสูงทั้งสามด้าน ส่วน EPSS ของตัวนี้อยู่ที่ 0.777% (ราวเปอร์เซ็นไทล์ที่ 56) ซึ่งเป็นการประเมินโอกาสถูกโจมตี ไม่ใช่ข้อมูลว่าถูกโจมตีแล้ว ในหน้า advisory ที่ผมเปิดไม่มีตัวไหนระบุว่าพบการโจมตีจริง และฟีดที่ผมใช้ตรวจ CISA KEV ก็ไม่มีตัวไหนในรายการนี้
ข้อควรระวังเรื่องวันที่ GitHub ลง advisory ของ TokenGuard และ relationship เมื่อ 19 ต.ค. แต่ Packagist บันทึกเป็น 23 ต.ค. เลยเห็นเป็นข่าวพร้อมกันหมดในวันนั้น ผมใช้วันที่ 23 ต.ค. เป็นหลักตาม Packagist
รุ่นที่กระทบและรุ่นที่แก้
ตัวเลขข้างล่างอ่านจากหน้า advisory ของแต่ละตัว
| แพ็กเกจ | รุ่นที่กระทบ | รุ่นที่แก้ |
|---|---|---|
| laravel/framework TokenGuard | ต่ำกว่า 12.68.0 และ 13.0.0 ถึง 13.28.x | 12.68.0, 13.29.0 |
| laravel/framework relationship | 12.45.0 ถึงก่อน 12.68.0 และ 13.0.0 ถึงก่อน 13.27.0 | 12.68.0, 13.27.0 |
| laravel/framework debug page | ต่ำกว่า 12.69.0 และ 13.0.0 ถึงก่อน 13.30.0 | 12.69.0, 13.30.0 |
livewire #[Authorize] |
4.3.0 ถึงก่อน 4.4.8 (Livewire 3 ไม่โดน) | 4.4.8 |
| livewire DOM XSS | 3.0.0-beta.1 ถึง 3.8.2 และ 4.0.0-beta.1 ถึง 4.3.3 | 3.8.3, 4.3.4 |
| filament (ครบทุกตัว) | 4.0.0 ถึง 4.13.2 และ 5.0.0 ถึง 5.8.2 | 4.13.3, 5.8.3 |
| league/commonmark (ครบทุกตัว) | ตั้งแต่ 0.6.0 ถึง 2.10.1 ตามแต่ละตัว | 2.10.2 |
| symfony/http-foundation | 5.4.1 ถึงก่อน 5.4.54 และสายหลังจากนั้นตามที่ Symfony ลง | 5.4.54, 6.4.48, 7.4.21, 8.1.9 |
| phpseclib | ต่ำกว่า 3.0.57 และ 4.0.0 | 3.0.57, 4.0.1 |
ช่วง affected ของ TokenGuard เขียนว่า "ต่ำกว่า 12.68.0" ทั้งหมด แต่ประกาศไม่ได้ระบุรุ่นแก้ของสายก่อน 12 ที่ผมเห็น ถ้าแอปยังอยู่สายเก่ากว่านั้น ต้องย้ายขึ้น 12 ขึ้นไปก่อน
Livewire #[Authorize] มี 3 อาการ ลำดับคีย์ของพารามิเตอร์ที่ถูกสลับ (เช่นส่ง {"1": 2, "0": 1}) ทำให้การเช็กสิทธิ์ตรวจกับ record หนึ่งแต่ action ไปทำงานกับอีก record method ที่ใช้ทั้ง #[On] กับ #[Authorize] เป็นแบบเดียวกัน และ method #[Json] รันตัวโค้ดก่อนเช็กสิทธิ์ (ตอบ 403 ก็จริง แต่การเขียนฐานข้อมูลเกิดไปแล้ว) กระทบเฉพาะแอปที่ใช้ attribute นี้ ถ้าเช็กสิทธิ์ด้วย $this->authorize(...) ในตัว method ไม่โดน
รุ่นนี้ reject request ที่พารามิเตอร์ของ call หรือ event ไม่ใช่ list หรือคีย์ชื่อ string ถ้าฝั่ง client ของแอปเคยส่งแบบแปลกๆ ให้ทดสอบหลังอัปเดต ถ้ายังอัปเดตไม่ได้ ทางชั่วคราวของ advisory คือย้ายการเช็กสิทธิ์ไปเรียก $this->authorize(...) ในตัว method
Filament รอบนี้มี advisory 4 ตัว ทั้งหมดเกี่ยวกับ MFA และหน้า login ตัวที่หนักสุดคือ CVE-2026-77567 (High, 8.1) ที่ข้ามขั้น MFA ได้เมื่อเปิด recovery codes ตัวอื่นคือรหัส app เก่าใช้ซ้ำได้ราว 4 นาทีตามค่าเริ่มต้นถ้าผู้โจมตีมีรหัสผ่านกับรหัสหนึ่งตัวอยู่แล้ว, หน้า login ยืนยันได้ว่ารหัสผ่านถูกสำหรับบัญชีที่ถูกห้ามเข้า panel, และ action จัดการ MFA ไม่ถามรหัสผ่านซ้ำ ทั้งหมดไม่กระทบ MFA แบบอีเมล และไม่มี workaround อัปเดตเป็น 4.13.3 หรือ 5.8.3 ครอบคลุมทั้งชุด
league/commonmark มี advisory 12 ตัว ตั้งแต่ 6 ส.ค. ถึง 30 ก.ย. ส่วนใหญ่เป็น denial of service (CPU หมดจากการ parse Markdown ที่ประกอบมาเฉพาะ) แต่มี XSS สองตัวที่สำคัญกว่า ตัวหนึ่งคือ on* filter ของ AttributesExtension ที่ถูกข้ามด้วยอักขระ form feed (2.7.0 ถึงก่อน 2.9.1) อีกตัวคือ DisallowedRawHtml ที่ปล่อย <script ผ่านเมื่อชื่อแท็กอยู่ท้ายบรรทัด (1.3.0 ถึง 2.10.1) ทั้งสองกระทบแอปที่ render Markdown ของผู้ใช้ที่ไม่น่าเชื่อถือ ทางลดเสี่ยงของตัวหลังคือตั้ง html_input เป็น escape หรือ strip และของตัวแรกคือกำหนด attributes.allow เป็นรายการชัดเจน ส่วนรุ่นแก้ผมเปิดอ่านครบแค่ 3 หน้า (2.9.1 กับ 2.10.2) ที่เหลือคิดจากช่วง affected ซึ่งทุกตัวจบที่ 2.10.1 หรือก่อนหน้า เลย 2.10.2 พ้นทั้งหมด
Symfony HeaderUtils::split() เสีย CPU แบบทวีคูณเมื่อ header Cache-Control มีช่องว่างต่อกันยาว (ราว 813 มิลลิวินาทีต่อ request ที่มี 17 ช่องว่างบน PHP 8.5 และเพิ่มเป็นสองเท่าทุกช่องว่าง) ใครรับ HTTP request ผ่าน Symfony ก็เข้าถึงได้โดยไม่ต้องล็อกอิน รุ่น 6.4.46, 7.4.19 และ 8.1.7 เป็นรุ่นแรกที่แก้ แต่มี regression เรื่อง split('foo bar', ' ') ให้ใช้ 6.4.48, 7.4.21 หรือ 8.1.9 แทน หน้าของ Symfony ลงเมื่อ 15 ต.ค. ส่วนฟีด Packagist บันทึกเป็น 15 ก.ย. และ GitHub Advisory Database ลง GHSA-r925-mgvr-h9cc เมื่อ 27 ต.ค. พร้อมระดับ High (CVSS v4 8.7) สามแหล่งวันที่ไม่ตรงกัน ผมใช้วันที่ตามหน้า Symfony ซึ่งเป็นต้นทาง หน้าของ Symfony เองไม่ให้คะแนน CVSS
phpseclib (CVE-2026-84308) ต้องเข้าเงื่อนไขหลายข้อพร้อมกัน ใช้คีย์ X25519 ตัวเดียวซ้ำนาน, เส้นทาง pure-PHP ทำงาน (ไม่มี ext-sodium) และผู้โจมตีต้องวัดเวลาได้ละเอียดในระดับเครื่องเดียวกัน ผู้เขียนเองเรียกว่า hardening issue ไม่ใช่ remote exploit ที่สมบูรณ์ ลำดับความสำคัญเลยอยู่ท้ายสุด
วิธีแก้
- ดูรุ่นที่ลงอยู่ ใน repo ของโปรเจกต์ ไม่ใช่บนเครื่อง dev อย่างเดียว
- รัน composer audit ดูรายการที่ Composer เห็นเองจากฐานข้อมูล advisory
- อัปเดตหกแพ็กเกจพร้อมกัน พร้อม dependency ที่เกี่ยวข้อง
- รีสตาร์ต worker queue, Octane และ PHP-FPM ให้ใช้โค้ดใหม่
- ทดสอบ route ที่ใช้ guard แบบ token และ Livewire action ที่ใช้ #[Authorize] ก่อนปล่อยเต็มระบบ
# ดูรุ่นของทั้งหกตัวที่ลงอยู่ในโปรเจกต์
composer show | grep -E '^(laravel/framework|livewire/livewire|filament/filament|league/commonmark|symfony/http-foundation|phpseclib/phpseclib) '
# เทียบกับฐานข้อมูล advisory (ใช้ --locked ใน CI ได้)
composer audit
composer update laravel/framework livewire/livewire filament/filament \
league/commonmark symfony/http-foundation phpseclib/phpseclib --with-dependencies
composer audit
php artisan optimize:clear
php artisan queue:restart
ถ้า composer.json ล็อกช่วงรุ่นไว้แคบกว่ารุ่นแก้ (เช่น ~12.40.0) คำสั่งข้างบนจะไม่ขยับ ให้ปรับ constraint ก่อน ส่วนแอปที่ใช้ Filament ให้ดูด้วยว่า plugin ของ Filament ที่ลงไว้ยังรองรับรุ่นใหม่ ถ้าไม่ใช่ composer update จะแจ้ง conflict ให้เห็นเอง
เรื่อง debug ให้เช็กทุกสภาพแวดล้อมที่เปิดออกอินเทอร์เน็ต
php artisan about --only=environment
grep -n '^APP_DEBUG' .env
ค่าต้องเป็น APP_DEBUG=false ใน production อยู่แล้วตามหลักทั่วไป แต่ CVE-2026-102279 เป็นตัวเตือนว่าหน้า debug เป็นพื้นผิวโจมตีด้วยตัวมันเอง ไม่ใช่แค่ที่รั่วข้อมูล
เช็กว่าโดนหรือยัง
ไม่มี advisory ตัวไหนในชุดนี้ประกาศ indicator of compromise ผมเลยมีแค่แนวทางที่ประมวลจากคำอธิบายช่องโหว่เอง ไม่ใช่รายการจากต้นทาง
สำหรับ TokenGuard ผมอนุมานว่าถ้าคนยิงจริงจะส่งค่า token มาเป็น array หรือ object แทนที่จะเป็นข้อความธรรมดา ลองไล่ access log ของ route ที่เป็น API ดูพารามิเตอร์รูปแบบ array
grep -E 'api_token(\[|%5B)' /path/to/access.log | head
คำสั่งนี้เห็นเฉพาะ query string ถ้า token ส่งมาใน JSON body หรือ header จะไม่เห็นใน log ปกติ ที่เหลือคือดูผลที่ปลายทาง เช่นผู้ใช้คนเดียวมี session หรือการเรียก API จาก IP แปลกๆ ติดกัน, ข้อมูลในตารางที่ผูกกับ endpoint อ่านข้อมูลหายไปผิดปกติ (กรณี CVE-2026-114508), การเปลี่ยน MFA ของบัญชี Filament ที่เจ้าของไม่ได้ทำ ใครมี backup ฐานข้อมูลล่าสุดควรเก็บไว้ก่อนอัปเดต เพราะข้อมูลที่ถูกลบจากตัวหลังกู้ได้ทางเดียวคือ backup
ส่วนตัวผม ถ้าแอปมี route ที่ใช้ guard แบบ token เปิดออกอินเทอร์เน็ต ควรอัปเดต Laravel เป็นรอบเร่งด่วนนอกตารางปกติ เพราะข้ามการยืนยันตัวตนได้ทั้งระบบและแก้ได้ด้วยการอัปเดตเลขเวอร์ชัน ส่วน Filament ที่เปิด MFA ควรทำในรอบเดียวกัน ที่เหลือ (commonmark, Symfony, phpseclib, Livewire 3) เข้ารอบบำรุงรักษาปกติก็ได้ ตามความเสี่ยงของแต่ละแอปว่ารับ Markdown จากคนนอกหรือไม่ ส่วนช่วงรุ่นกับเงื่อนไขทั้งหมดข้างบนเทียบกับ composer.lock ของแต่ละโปรเจกต์ได้เลย
ปล. บทความเกี่ยวกับ Laravel ที่ผมเขียนไว้ก่อนหน้านี้ เรื่องตรวจความปลอดภัยแอปที่ deploy แล้ว ดูต่อได้ที่ Laravel security audit
ที่มา: GitHub Advisory Database (github.com/advisories/GHSA-f9x3-7vq9-cph6, GHSA-5wcm-3v2w-8362, GHSA-jh5r-qr3c-85q8, GHSA-mhf7-xp6r-6qrc, GHSA-g3hc-697w-wm82, GHSA-52xp-w8hr-xv3c, GHSA-r3j6-gpjw-qfjr, GHSA-xwpv-pqxp-5v36, GHSA-7m6h-rg42-m449, GHSA-3q6v-r5mr-hxv8, GHSA-97jj-33gv-5xf9, GHSA-f8fg-pg57-v4j8, GHSA-q97c-8qh3-fpc6), Packagist Security Advisories API (packagist.org/api/security-advisories), Symfony (symfony.com/cve-2026-108082) ข้อมูลถึง 5 พ.ย. 2026 ถ้า advisory เพิ่มหรือรุ่นแก้เปลี่ยน เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
อยากให้เราทำให้ไหม?
ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย