Brotli อยู่ใน PHP บน Windows ตรงไหน
Brotli เป็นวิธีบีบอัดข้อมูลแบบเดียวกับ gzip ที่เว็บใช้ส่งหน้าเว็บให้เล็กลง เครื่องที่รับข้อมูลต้องคลายกลับก่อนอ่าน
ใน zip ของ PHP สำหรับ Windows มีไฟล์ brotlidec.dll วางอยู่ข้าง extension cURL เพื่อให้ cURL คลายข้อมูล Brotli ได้ ตัวที่มีช่องโหว่คือส่วนคลายข้อมูลนี้ ตามประกาศของ php.net โค้ด PHP จะไปถึงส่วนนี้ได้เมื่อเปิดให้ cURL คลายข้อมูลที่ตอบกลับมาเอง
ข้อมูลที่ทำขึ้นมาเฉพาะทำให้ PHP เขียนข้อมูลเลยขอบเขตของหน่วยความจำ ตามข้อมูลของ CVE ผลอาจเป็นได้ตั้งแต่ process ล่ม ข้อมูลในหน่วยความจำรั่ว ไปจนถึงรันโค้ดได้ ช่องโหว่นี้แยกจาก PHP2Shell สองตัวที่แก้ไปเมื่อ 21 ต.ค. ซึ่งอยู่ในตัว PHP เอง
แอป Laravel ที่เรียก API ด้วย Http เปิดการคลายข้อมูลไว้แล้ว
ประกาศบอกว่า cURL ปิดการคลายข้อมูลอัตโนมัติไว้เป็นค่าเริ่มต้น แต่ไลบรารีที่ใช้เรียก HTTP เปิดให้เองได้ ซึ่ง Guzzle ที่อยู่ใต้ Http::get() ของ Laravel ก็เป็นแบบนั้น Guzzle ตั้ง decode_content เป็น true ไว้เป็นค่าเริ่มต้น แล้วสั่ง cURL ให้เปิดตัวคลายข้อมูลทุกแบบที่มี ซึ่งรวม Brotli ด้วย (ดูได้ใน CurlFactory.php ของ guzzlehttp/guzzle)
ดังนั้นแอป Laravel บน Windows ที่เรียก URL ภายนอก ก็มีทางไปถึง brotlidec.dll ได้ทันทีที่เครื่องปลายทางตอบกลับมาเป็น Brotli จุดที่เสี่ยงที่สุดคือโค้ดที่เรียก URL ที่ผู้ใช้ใส่มาเอง เช่น ดึงรูปจากลิงก์ ทำ link preview หรือ webhook ที่ให้ลูกค้าตั้ง URL เองได้ เพราะคนนอกเลือกได้ว่าจะให้เครื่องไหนตอบ ส่วนการเรียก API ของผู้ให้บริการที่เรารู้จักก็เสี่ยงน้อยกว่า แต่ไม่ถึงกับศูนย์
เครื่องแบบไหนต้องอัปเดต
| ที่ที่รัน PHP | ต้องทำอะไร |
|---|---|
| Windows Server ที่รัน PHP กับ IIS หรือ Apache | โหลด build -1 ของรุ่นที่ใช้อยู่มาแทน แล้วรีสตาร์ต IIS, Apache หรือ PHP-CGI และ queue worker |
| เครื่อง dev บน Windows (XAMPP, Laragon, WAMP) | อัปเดตด้วย แม้จะเป็นแค่เครื่อง dev เพราะโค้ดที่เราเขียนก็เรียก API ภายนอกจากเครื่องนี้ |
| Linux (Ubuntu, Debian, ondrej PPA, Docker image ทางการ) | build ชุดนี้ไม่เกี่ยว PHP บน Linux ใช้ cURL และ Brotli ของระบบ ให้ติดตามแพตช์ของ Brotli จาก OS แทน |
| PHP 8.1 บน Windows | ไม่มี build ใหม่ ยังเป็น build ของ ธ.ค. 2025 และไม่ได้แพตช์ PHP2Shell ด้วย ควรขึ้นรุ่นที่ยังมี support |
โหลด build ใหม่มาแทนตัวเดิม
- เปิดหน้าดาวน์โหลดสำหรับ Windows แล้วเลือกรุ่นเดียวกับที่ใช้อยู่ เช่น 8.3 ก็ใช้ 8.3.36-1
- เลือกให้ตรงกับของเดิมทั้งสองเรื่อง คือ x64 หรือ x86 และ Thread Safe หรือ Non Thread Safe ถ้ารันกับ Apache แบบ module มักเป็น Thread Safe ส่วน IIS ที่รันผ่าน FastCGI มักเป็น Non Thread Safe ถ้าไม่แน่ใจ ให้ดูบรรทัด Thread Safety ใน
phpinfo()ของเครื่องเดิม - แตกไฟล์ไปวางแทนโฟลเดอร์ PHP เดิม โดยเก็บ
php.iniตัวเดิมไว้ แล้วรีสตาร์ตทุก process ที่ใช้ PHP
ถ้าใช้ Laragon ปกติเราแตก zip ไปไว้ใน bin\php แล้วเลือกรุ่นใหม่จากเมนูได้เลย ส่วน XAMPP ไม่ได้ออกรุ่นตามทุกแพตช์ของ PHP ทางที่เร็วกว่าคือแทนโฟลเดอร์ php เองแบบเดียวกัน
เลข php -v ของ build -1 ยังขึ้นเป็น 8.3.36 เหมือนเดิม เพราะเป็นโค้ด PHP ชุดเดียวกัน ต่างกันแค่ไลบรารีที่ใส่มาด้วย เรื่องนี้คล้ายกับเลขเวอร์ชัน PHP ของ Ubuntu ที่เลขหลักไม่เปลี่ยนแต่แพตช์เปลี่ยน วิธีที่แน่นอนที่สุดคือจดไว้ว่าโหลด zip ตัวไหนมาลงเมื่อไร
ถ้ายังอัปเดตไม่ได้ทันที
ช่วงที่ยังลง build ใหม่ไม่ได้ ให้ปิดทางที่ข้อมูลจากคนนอกจะเข้ามาถึงตัวคลาย Brotli ก่อน
- ปิด
decode_contentของ Guzzle ในโค้ดที่เรียก URL ที่ผู้ใช้ใส่มาเอง เช่นHttp::withOptions(['decode_content' => false])cURL จะไม่คลายข้อมูลที่บีบอัดมาให้ แต่โค้ดส่วนนั้นต้องรับมือกับข้อมูลที่ยังบีบอัดอยู่เอง - หยุดฟีเจอร์ที่ดึง URL ตามที่ผู้ใช้ส่งมาไว้ชั่วคราว ถ้าระบบมี
ทั้งสองข้อเป็นแค่ทางกันระหว่างรอ ทางแก้จริงคือ build -1






