ความปลอดภัยและการเข้าถึง

ปิด AIO หรือ SSI บน NGINX เพื่อลดความเสี่ยง CVE-2026-97205 พร้อมวิธีตรวจสอบ

หาก NGINX เปิด AIO ร่วมกับ SSI อยู่ เราสามารถปิดฟีเจอร์ใดฟีเจอร์หนึ่งเพื่อลดความเสี่ยงจาก CVE-2026-97205 ระหว่างรออัปเดตแพ็กเกจได้ ถ้าเว็บไซต์ยังใช้ SSI ประกอบหน้าเว็บ ให้เริ่มพิจารณาปิด AIO ส่วนเว็บไซต์ที่ไม่ต้องใช้ SSI สามารถปิด SSI แทนได้

แผนภาพสองทางเลือกเพื่อลดความเสี่ยง ปิด AIO โดยคง SSI หรือปิด SSI เพื่อหยุดประมวลผลคำสั่งในหน้าเว็บ

ตรวจข้อมูลวันที่ 28 ตุลาคม 2026 ภาพเป็นแผนภาพประกอบ ส่วนผลทดสอบด้านล่างเป็นเกณฑ์ที่คาดหวัง ไม่ใช่ผลจากเซิร์ฟเวอร์ของผู้เขียน

ช่องโหว่นี้เกี่ยวกับอะไร

CVE-2026-97205 เป็น use-after-free หรือการกลับไปใช้พื้นที่หน่วยความจำที่ถูกคืนไปแล้ว เกิดได้ในบางรูปแบบที่เปิด asynchronous file I/O หรือ AIO ร่วมกับหน้า Server Side Includes หรือ SSI ที่มี include virtual

ผู้โจมตีจากเครือข่ายอาจทำให้ worker process ล่มหรือหน่วยความจำเสียหาย และอาจรันโค้ดได้เมื่อ ASLR ถูกปิดหรือถูกข้าม ตาม ประกาศของ Red Hat ซึ่งระบุวิธีลดความเสี่ยงไว้เป็นการปิด AIO หรือ SSI

ตัวอย่างนี้ใช้ NGINX บน Linux ที่จัดการ service ด้วย systemd หากรันใน container ให้ตรวจ config และ reload ภายใน container ที่ให้บริการจริง

ตรวจว่าเปิดฟีเจอร์ที่เกี่ยวข้องหรือไม่

ดูเวอร์ชันและ config รวมไฟล์ที่ถูก include

nginx -v
sudo nginx -T

มองหาค่าที่เปิด AIO เช่น

aio on;

หรือ

aio threads;

รวมถึง

ssi on;

อ่านบริบทของ http, server, location และเส้นทาง subrequest ที่เกี่ยวข้องด้วย การเจอ aio กับ ssi คนละส่วนของไฟล์ยังไม่พอจะสรุปว่ามีเส้นทางที่ได้รับผลกระทบ และไม่ควรสมมติว่าใช้ aio threads แล้วจะหลีกเลี่ยงช่องโหว่ได้

ค่าเริ่มต้นคือ aio off; และ ssi off; แต่ไฟล์ที่ include หรือ location ย่อยอาจเปิดกลับมาได้ ตาม เอกสาร AIO และ เอกสาร SSI

วิธีที่ 1 ปิด AIO และคง SSI ไว้

หากเว็บไซต์ยังใช้ SSI รวม header, footer หรือข้อมูลจาก URL อื่น ให้พิจารณาปิด AIO เพื่อคงการประกอบหน้าเว็บไว้ สำรองไฟล์ก่อน แล้วเปลี่ยนทุกจุดที่เกี่ยวข้องจาก aio on; หรือ aio threads; เป็น

aio off;

ตัวอย่าง location เดิม

location /pages/ {
    root /var/www/site;
    aio threads;
    ssi on;
}

หลังแก้

location /pages/ {
    root /var/www/site;
    aio off;
    ssi on;
}

ตัวอย่างนี้แสดงเฉพาะค่าที่ต้องเปลี่ยน ให้คง root, alias, authentication และค่าอื่นของเว็บไซต์จริงไว้ และตรวจ location ที่ SSI เรียกผ่าน include virtual ด้วย

ถ้าวาง aio off; ที่ระดับ http ต้องตรวจว่าไม่มี server หรือ location ย่อยเปิด AIO ซ้ำ การปิด AIO เปลี่ยนวิธีอ่านไฟล์ จึงควรตรวจเวลาในการตอบกลับและการใช้ทรัพยากรกับโหลดใกล้เคียงงานจริง โดยเฉพาะระบบที่ให้บริการไฟล์ขนาดใหญ่ ดู เอกสาร AIO

วิธีที่ 2 ปิด SSI หากเว็บไซต์ไม่ต้องใช้

เปลี่ยนส่วนที่เปิด SSI เป็น

ssi off;

ตรวจทุก location รวมถึง if ภายใน location หากมีการตั้ง ssi on; ไว้ อย่าเพิ่ม ssi off; ซ้ำใน scope เดียวกัน ให้แก้บรรทัดเดิม

หลังปิด NGINX จะหยุดประมวลผลคำสั่ง SSI ใน response หน้าเว็บที่พึ่งพา SSI อาจมีเนื้อหาหายไป และคำสั่งหรือ path ที่เคยอยู่ใน HTML comment อาจถูกส่งออกไปตามต้นฉบับ จึงควรตรวจหน้าเว็บจริงก่อนเลือกวิธีนี้ ตามพฤติกรรมของ โมดูล SSI

เลือกวิธีที่เหมาะกับระบบ ไม่จำเป็นต้องปิดทั้งสองฟีเจอร์พร้อมกันตามแนวทางลดความเสี่ยงในประกาศ

ตรวจ config แล้ว reload

เริ่มจากตรวจ syntax

sudo nginx -t

เมื่อผ่านแล้วจึง reload และดูสถานะ รันทีละคำสั่งและหยุดตรวจสาเหตุหากมี error

sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
sudo journalctl -u nginx --since "5 minutes ago" --no-pager

ดู error log ของ NGINX เพิ่มเติมด้วย การที่ service ยังเป็น active ไม่ได้ยืนยันว่าใช้ config ใหม่ ต้องตรวจว่าไม่มี error ในการนำ config มาใช้ และ worker เดิมระบายงานเสร็จแล้ว ตาม เอกสารการ reload

ทดสอบเมื่อเลือกปิด AIO

หลังแก้ ให้ตรวจ nginx -T อีกครั้ง อ่าน scope และไฟล์ที่ include ให้ครบ เพื่อยืนยันว่าไม่มี AIO เปิดอยู่ในเส้นทางที่เกี่ยวข้อง จากนั้นตรวจผล reload และทดสอบหน้า SSI รวมถึงไฟล์ที่เว็บไซต์ใช้งานจริง

sudo nginx -T

เมื่อปิด AIO แต่คง SSI หน้าเว็บควรยังประกอบเนื้อหาได้ตามเดิม อย่างไรก็ตาม curl ไม่ได้แสดงว่า NGINX ใช้ AIO หรือไม่ การได้ HTTP 200 จึงเป็นเพียงผลทดสอบการใช้งาน ต้องตรวจ config และการ reload ประกอบด้วย

nginx -T อ่านไฟล์บนดิสก์ ไม่ได้อ่านค่าที่ resolve แล้วจากหน่วยความจำของ worker ตาม คู่มือคำสั่ง NGINX จึงไม่ควรใช้ผลคำสั่งนี้อย่างเดียวสรุปว่า process เปลี่ยนแล้ว

ทดสอบเมื่อเลือกปิด SSI

ทดสอบใน staging โดยวางไฟล์ HTML ภายใต้ location เดิมที่ต้องการตรวจ ไม่สร้าง location ใหม่ที่มีค่า SSI ต่างออกไป และไม่เปิด SSI เพิ่มบน production เพียงเพื่อเก็บผลก่อนแก้

สร้างไฟล์ ssi-check.html ใต้ document root ที่ URL ของไฟล์เข้าถึงได้เป็น /ssi-check.html

BEGIN
<!--# include virtual="/ssi-fragment.txt" -->
END

สร้างไฟล์ ssi-fragment.txt ให้เรียกผ่าน URL /ssi-fragment.txt ได้

SSI_INCLUDE_OK

นี่เป็นการเรียก SSI ปกติเพื่อตรวจพฤติกรรม ไม่ใช่ payload สำหรับกระตุ้นช่องโหว่ รูปแบบ include virtual อ้างอิงจาก คู่มือ SSI ของ NGINX

ใช้ curl เรียกตรง origin โดยเปลี่ยนโดเมนและ IP เป็นของจริง หาก location ใช้ URL prefix ให้ปรับ URL และ path ของ fragment ให้ตรงกับเว็บไซต์

curl --noproxy '*' \
  --resolve example.com:443:203.0.113.10 \
  --max-time 10 -i \
  https://example.com/ssi-check.html

ตรวจว่าได้ไฟล์ที่ถูกต้อง มี Content-Type: text/html และ response ไม่ได้มาจาก cache จากนั้นเปรียบเทียบ body โดยผลด้านล่างเป็นตัวอย่างที่คาดหวัง

ก่อนแก้ เมื่อ SSI ทำงาน

BEGIN
SSI_INCLUDE_OK
END

หลังใช้ ssi off;

BEGIN
<!--# include virtual="/ssi-fragment.txt" -->
END

หากเลือก aio off; และคง ssi on; ผลยังควรเป็นแบบที่ SSI ประกอบเนื้อหาแล้ว การทดสอบนี้จึงตรวจการปิด SSI ได้ แต่ไม่ใช่เครื่องมือตรวจ AIO

ดู body จาก curl เพราะเบราว์เซอร์จะซ่อน HTML comment ทดสอบให้ครอบคลุมทุกเส้นทางที่เกี่ยวข้อง ลบไฟล์ทดสอบที่สร้างเพิ่มเมื่อเสร็จ และตรวจหน้าเว็บจริงอีกครั้ง หากไม่มี baseline ที่ SSI เคยประมวลผลได้ การเห็นคำสั่งดิบเพียงครั้งเดียวยังบอกไม่ได้ว่าเกิดจาก config ที่เพิ่งแก้

วิธีที่เลือกหลักฐานที่ต้องตรวจ
ปิด AIOConfig ครอบคลุมเส้นทางที่เกี่ยวข้อง ไม่มีค่าเปิดซ้ำ reload สำเร็จ และ worker เดิมจบงานแล้ว
ปิด SSIหลักฐาน config และ reload ร่วมกับผลก่อน–หลังที่คำสั่ง SSI ไม่ถูกประมวลผล
ทั้งสองวิธีเว็บไซต์จริงยังทำงานตามที่ต้องการ และตรวจครบทุก instance

อัปเดตแพ็กเกจเพื่อแก้ตัวบั๊ก

NGINX upstream แก้ CVE-2026-97205 ในสาย stable ตั้งแต่ 1.30.6 และ mainline ตั้งแต่ 1.31.7 ตาม NGINX Security Advisories หากใช้แพ็กเกจ Ubuntu ให้เทียบเลขแพ็กเกจเต็มกับ USN-8955-1 เพราะมีการนำแพตช์มาใส่ในรุ่นเดิมได้

หลังอัปเดตต้องตรวจว่า process ใช้ binary ที่มีแพตช์แล้ว การ reload config อย่างเดียวไม่โหลด executable ใหม่ หากใช้ systemctl restart nginx ให้เลือกช่วงที่รับการหยุดและเริ่ม service ได้ แล้วตรวจ log และการใช้งานอีกครั้ง การผ่านเกณฑ์ปิด AIO หรือ SSI เป็นหลักฐานการลดความเสี่ยงตาม config ส่วนการยืนยันว่าแก้ตัวบั๊กแล้วต้องมีหลักฐานแพ็กเกจและ binary ที่กำลังทำงานด้วย

EOF.← กลับไปอ่านบทความอื่น