Log4Shell Apocalypse: เมื่อฟังก์ชัน print log ธรรมดา กลายเป็นประตูนรกข้ามคืน
⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 45 วินาที
ในบรรดาคำสั่งที่โปรแกรมเมอร์ไว้ใจที่สุดในชีวิต คงไม่มีอะไรง่ายและไร้เดียงสาไปกว่าคำสั่ง "พ่น Log" อีกแล้ว
มันจะไปอันตรายได้ยังไง? ก็แค่เอาข้อความไปแปะลงไฟล์ Text... แต่ในเดือนธันวาคม 2021 โลกทั้งใบต้องตื่นตระหนก เมื่อข้อความในวงเล็บนี้ กลายเป็นช่องโหว่ระดับคะแนนเต็ม CVSS 10.0 ที่แฮกเกอร์สามารถสั่งยึด Server ได้ทั้งเครื่อง โดยไม่ต้องรู้รหัสผ่านสักตัวเดียว!
🤯 ฟีเจอร์ที่ไม่มีใครขอ แต่ทีมงานจัดให้
ย้อนกลับไปหลายปีก่อนหน้า ทีมพัฒนา Apache Log4j อยากเพิ่มความฉลาดให้ระบบ Log พวกเขาเลยใส่ฟีเจอร์หนึ่งที่ชื่อว่า Message Lookup (ผ่านโปรโตคอล JNDI)
ไอเดียคือ: "ถ้า Log เจอข้อความแบบ ${java:version} แทนที่จะพิมพ์ตรงๆ ให้ไประเบิดเอาเวอร์ชันของ Java มาแสดงแทนนะ จะได้สะดวก"
ฟังดูเท่และหวังดี... แต่ความฉลาดเกินเบอร์คือ มันดันรองรับ LDAP ด้วย! นั่นหมายความว่า ถ้าเราส่ง URL แปลกปลอมเข้าไป ตัว Log4j จะหน้าซื่อใจคด วิ่งออกไปโหลดโค้ด Java จากภายนอกมาคอมไพล์และรันในเครื่องตัวเองทันที!
💥 คาถามหาประลัยบรรทัดเดียว
แฮกเกอร์ไม่ต้องแฮก Database ไม่ต้องเดารหัสผ่าน เขาแค่เดินไปที่หน้า Login หรือช่องค้นหา แล้วพิมพ์ชื่อผู้ใช้ว่า:
สิ่งที่เกิดขึ้นในระดับ Server:
- แอปพลิเคชันรับค่าเข้ามา แล้วสั่ง
logger.info("Login failed: " + username) - Log4j เห็น syntax
${jndi:...}เลยอุทานว่า "อ๋อ มีตัวแปรให้ค้นหานี่หว่า!" - Log4j ยิง Request วิ่งออกเน็ตไปหาเซิร์ฟเวอร์ของแฮกเกอร์ เพื่อไปดาวน์โหลดไฟล์
malware.class - JVM รันโค้ดชั่วร้ายนั้นทันทีด้วยสิทธิ์เต็มของ App... เกมจบ เซิร์ฟเวอร์โดนยึดเรียบร้อย
ความหลอนคือจุดนั้นไม่มีใครรู้ว่าข้อความจะไหลไปโผล่ที่ไหน แฮกเกอร์เอา String นี้ไปตั้งเป็นชื่อ iPhone, ชื่อตัวละครในเกม Minecraft, หรือแม้กระทั่ง User-Agent ของ Browser เพื่อหวังให้ระบบหลังบ้านเผลอหยิบไป Log สักที่
💡 5-Min Takeaway
"ความฉลาดเกินความจำเป็น คือบ่อเกิดของหายนะ" เครื่องมือที่มีหน้าที่แค่พิมพ์ข้อความ ไม่ควรมีความสามารถในการประมวลผลโค้ด (Execute) หรือวิ่งออกอินเทอร์เน็ต และกฎเหล็กของความปลอดภัยยังคงเหมือนเดิมเสมอ: อย่าไว้ใจ Input จากภายนอก แม้กระทั่งตอนจะบันทึกมันลง Log ก็ตาม