SSRF: แค่ฟีเจอร์ "ดึงรูปโปรไฟล์จาก URL" ทำไมแฮกเกอร์ถึงแอบสูบกุญแจลับ AWS ไปได้หมดทั้งคลาวด์?
⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 30 วินาที
คุณทำฟีเจอร์เอาใจผู้ใช้งาน: "เปลี่ยนรูปโปรไฟล์ได้ง่ายๆ แค่แปะ URL ลิงก์รูปภาพจากอินเทอร์เน็ต แล้วให้ Backend แอบดาวน์โหลดมาเก็บไว้ใน S3 ให้"
โค้ดสั้นๆ แค่ 2 บรรทัดทำงานได้อย่างราบรื่น:
val imageBytes = httpClient.get(userProvidedUrl).bodyAsBytes()
s3Client.upload(imageBytes)
จนกระทั่งบ่ายวันหนึ่ง มีแฮกเกอร์คนหนึ่งไม่ได้ส่ง URL รูปแมวเข้ามา... แต่เขาส่งที่อยู่ปริศนานี้เข้ามาแทน:
และในเสี้ยววินาทีต่อมา เซิร์ฟเวอร์ของคุณก็ตอบกลับพร้อม AccessKeyId, SecretAccessKey และ SessionToken ของระบบ AWS ส่งตรงถึงมือแฮกเกอร์อย่างสุภาพ! เกิดอะไรขึ้น?
🕵️ ยืมมือฆ่าคน: ช่องโหว่ SSRF (Server-Side Request Forgery)
ตามปกติ บริษัทจะสร้าง Firewall กั้นไว้อย่างแน่นหนา แฮกเกอร์จากอินเทอร์เน็ตภายนอกไม่มีวันยิงเข้าหา IP วงใน (Internal Network / Intranet) ได้โดยตรง
แต่ช่องโหว่ SSRF คือการที่แฮกเกอร์ไม่ได้ยิงเอง แต่ "สั่งให้เซิร์ฟเวอร์ของคุณ (ซึ่งนั่งอยู่หลัง Firewall) เป็นคนยิง Request แทน!"
"เหมือนยามหน้าประตูที่ซื่อสัตย์... ถ้าคนแปลกหน้าจะเดินเข้าตึก ยามจะสกัดไว้ แต่ถ้าพนักงานในตึก (เซิร์ฟเวอร์ของเรา) เดินไปหยิบของข้างในมาให้ ยามจะปล่อยผ่าน 100%!"
☁️ เลขอาถรรพ์ 169.254.169.254 คืออะไร?
บนระบบคลาวด์ยอดนิยม เช่น AWS EC2, Google Cloud, Azure หรือ DigitalOcean จะมีที่อยู่ IP วิเศษ (Link-local address) ตัวหนึ่งเหมือนกันหมดคือ 169.254.169.254 เรียกว่า Instance Metadata Service (IMDS)
- มันคือ API ภายในเครื่อง เพื่อให้แอปที่รันอยู่บน VM ขอกุญแจชั่วคราว (IAM Role) ไปคุยกับ S3 หรือ RDS โดยไม่ต้องใส่รหัสผ่านค้างไว้ในโค้ด
- ในระบบเวอร์ชันดั้งเดิม (IMDSv1) ใครก็ตามที่รันอยู่ในเครื่อง แค่ยิง
GET http://169.254.169.254/...ก็จะได้กุญแจลับระดับ Admin หลุดออกมาทันทีโดยไม่ต้องใช้รหัสผ่านใดๆ!
💥 คดีประวัติศาสตร์: Capital One Data Breach (2019)
หนึ่งในการโจรกรรมข้อมูลที่โด่งดังที่สุดในโลกของธนาคาร Capital One ซึ่งทำให้ข้อมูลลูกค้ากว่า 100 ล้านคน ถูกขโมย เกิดขึ้นจากช่องโหว่ SSRF ใน Web Application Firewall (WAF) ตัวหนึ่ง
แฮกเกอร์สั่งให้ WAF ตัวนั้นยิงไปดึงสิทธิ์จาก 169.254.169.254 แล้วเอากุญแจ IAM Role ที่ได้ไปสั่งดาวน์โหลดข้อมูลบัตรเครดิตทั้งหมดออกจากถัง AWS S3 Bucket กวาดไปจนเกลี้ยง!
🛡️ 2 คาถาป้องกัน SSRF: ดัดหลัง URL และล็อกตาย IMDSv2
1. บังคับย้ายไปใช้ AWS IMDSv2 (Session-oriented Token):
AWS ออกมาตรฐาน IMDSv2 มาเพื่อปราบ SSRF โดยเฉพาะ: การจะขอ Metadata ได้ ต้องส่งคำสั่ง PUT พร้อม Header พิเศษไปขอบัตรคิวก่อน ถึงจะเอาไป GET ได้ ซึ่งฟังก์ชันดาวน์โหลดรูปทั่วไปมักยิงได้แค่ GET ธรรมดา จึงเจาะไม่เข้าอีกต่อไป
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-endpoint enabled
2. ตรวจสอบ IP ปลายทางก่อนยิง (Egress IP Filtering):
ห้ามเชื่อใจ URL ที่ผู้ใช้ส่งมาเด็ดขาด! ก่อนจะสั่งให้ HTTP Client ดาวน์โหลดของ ต้องทำการ Resolve DNS ออกมาเป็น IP ก่อนเสมอ:
- ถ้าผลลัพธ์ตกอยู่ในช่วง Private IP (เช่น
127.0.0.1,10.0.0.0/8,192.168.0.0/16) หรือ169.254.0.0/16➔ ต้องปฏิเสธและทิ้งคำขอทันที! - ระวัง DNS Rebinding Attack: ต้องนำ IP ที่ผ่านการตรวจสอบแล้วไปใช้เชื่อมต่อจริงเท่านั้น
💡 5-Min Takeaway
"เมื่อใดก็ตามที่เซิร์ฟเวอร์ของคุณต้องยิง Request ออกไปตามคำสั่งของผู้ใช้ นั่นคือจุดเสี่ยงสูงสุดของระบบ" อย่ามองแค่ความถูกต้องของข้อมูลภายนอก แต่ต้องระวังไม่ให้เซิร์ฟเวอร์กลายเป็นสะพานเชื่อมให้ผู้ไม่หวังดีเข้ามาสำรวจเครือข่ายภายใน จงปิดการใช้งาน IMDSv1 บนคลาวด์ทุกเครื่องตั้งแต่วันนี้ และกรอง Private IP ทุกครั้งก่อนส่งคำขอดาวน์โหลด เพื่อไม่ให้กุญแจบ้านของคุณหลุดไปอยู่ในมือของคนอื่น