เรื่องราว ~/.ssh/known_hosts: ไฟล์เล็ก ๆ ที่เกี่ยวข้องความปลอดภัย SSH ที่น่าใส่ใจ
ในฐานะผู้ใช้งาน Linux หรือผู้ดูแลระบบ การใช้งาน SSH (Secure Shell) เป็นสิ่งที่คุ้นเคยกันดีในการเชื่อมต่อไปยังเครื่องที่เราต้องการบริหารจัดจากระยะไกล ครั้งแรกที่เราเชื่อมต่อไปยัง server โดยปกติจะต้องมีการเขียนข้อมูลบางอย่างลงไปที่ known_hosts ในไดเรกทอรี ~/.ssh/ หรือ ทุกการเชื่อมต่อกลับไป server เดิมซ้ำ ทุกคร้้งจะต้องอ่านข้อมูลบ้างอย่างจาก know_hosts เสมอ บทความนี้จะเรื่องราวของไฟล์นี้ให้ฟัง โดยเฉพาะอย่างยิ่งการเปลี่ยนแปลงที่เกิดขึ้นใน Linux เวอร์ชันใหม่ ๆ ซึ่งส่งผลต่อวิธีการจัดเก็บข้อมูลในไฟล์นี้อีกด้วย
known_hosts คืออะไร และทำไมถึงน่าสนใจ
เมื่อเชื่อมต่อ SSH server ครั้งแรก ไม่ว่าจะเป็น IP Address หรือ Hostname ก็จะได้รับข้อความประมาณนี้กลับมา
$ ssh root@cp0.d8k.io The authenticity of host 'cp0.d8k.io (152.42.244.80)' can't be established. ED25519 key fingerprint is SHA256:xlIAaGsZg6az+sGl74VyoVq+3ixBr1s8mvX3RIQDNjA. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])?
ข้อความนี้ทำให้รู้ว่า SSH Client เครื่องที่เรากำลังใช้งาน ไม่เคยเชี่อมต่อกับ server เครื่องนี้มาก่อน และการร้องขอการเชื่อมต่อครั้งนี้ ต้องการให้เรายืนยัน “SSH Fingerprint” ของ server ที่เรากำลังจะเชื่อมต่อ ถ้าเราตอบ yes และเชื่อมต่อสำเร็จ ข้อมูลของ server รวมถึง Fingerprint จะถูกเก็บไว้ในไฟล์ ~/.ssh/known_hosts
หน้าตาของ ~/.ssh/known_hosts ในรูปแบบเดิม ก็จะเป็นแบบนี้
cp0.d8k.io ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtGOV0JahD4JWjt0yABf+gI5pbGoAfRqc8gh5hbuNNx
SSH Fingerprint คืออะไร?
SSH Fingerprint เป็นค่า hash ที่สร้างขึ้นจาก public key ของ SSH server ตัวนั้น ดังนั้นค่า SSH Fingerprint ก็จะเป็นค่าเฉพาะตัวของ server ตัวนั้น ไม่ซ้ำกัน server ตัวอื่น ๆ ก็เปรียบได้กับลายนิ้วมือของคน ที่แต่ละคนก็จะไม่เหมือนกัน ดังนั้น SSH Fingerprint สามารถใช้ประโยชน์ได้ดังนี้
- สร้างความน่าเชื่อถือ เนื่องจาก SSH Client ใช้ fingerprint ยืนยันตัวตนของ server เครื่องนั้น ทุกครั้งทีเชื่อมต่อไปยัง server ถ้าเป็นครั้งแรก ก็จะมีการขอให้ยืนยัน และเขียนข้อมูลลงใน know_hosts และหามีการเชื่อมต่อในครั้งถัดไป ค่า fingerprint ในการเชื่อมต่อก็จะถูกนำมาเปรียบเทียบกับข้อมูลที่อยู่ใน know_hosts ทุกครั้ง
- ป้องการการปลอมแปลง หาก fingerprint ในขณะที่กำลังเชื่อมต่อ ไม่ตรงกับข้อมูลใน know_hosts แสดงว่ามีความผิดปกติเกิดขึ้น อาจจะถูกโจมตีด้วยเทคนิค Man-in-the-Middle ขึ้นได้ และ SSH Client จะตัดการเชื่อมต่อกับ server เครื่องนั้นทันที
การเปลี่ยนแปลง know_hosts ใน Linux ในปัจจุบัน
จากเดิมที่ know_hosts ถูกเก็บในรูปแบบที่มนุษย์สามารถอ่านได้ (Human Readable) ตามที่แสดงให้ดูในข้างต้น แต่ในปัจจุบัน อ้างอิงจาก Ubuntu ใน version 24.04.2 LTS (Noble Numbat) มีการเปลี่ยนค่า host name หรือ ip มาเป้น ค่า hash ทำให้จากเดิมที่อ่านได้ง่าย เป็นชุดตัวอักษร และตัวเลขที่ดูซับซ้อนมากขึ้น
|1|JOD8DQJMq46ye/TAwYSa0RvD8mc=|Q0RIF/smWDzFd0wMxKhDkKyhAlQ= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtGOV0JahD4JWjt0yABf+gI5pbGoAfRqc8gh5hbuNNx
จะ hash hostname ไปทำไม?
การ "Hashing Hostnames" ในไฟล์ known_hosts ของ SSH ซึ่งมีประโยชน์หลักๆ 3 ข้อคือ:
- ป้องกันการเปิดเผยข้อมูล (Prevent Information Disclosure): เมื่อ hash hostname ทำให้เห็นรายชื่อ server ที่เคยเชื่อต่อที่เก็บไว้ใน known_hosts ไม่ได้ ก็ทำให้ระบุเป้าหมายที่จะโจมตีได้ยากขึ้น ทำให้ลดการการขยายผลการเข้าถึง (Mitigate Lateral Movement) ได้
- ลดช่องโหว่ของ SSH Worm (Reduce SSH Worm Vulnerability): แก้ไขช่องโหว่ที่มัลแวร์สามารถใช้ไฟล์ known_hosts ที่เป็นข้อความธรรมดา (cleartext) เพื่อแพร่กระจายตัวเองได้
- เพิ่มความเป็นส่วนตัว (Enhance Privacy): ช่วยปกป้องความเป็นส่วนตัวของผู้ใช้โดยการซ่อนรูปแบบการเชื่อมต่อจากการสังเกตทั่วไป หรือการวิเคราะห์ไฟล์ known_hosts โดยไม่ได้รับอนุญาต
end of document