- ความมั่นคงปลอดภัยและการกำกับดูแลโดย CISO/
- บทวิเคราะห์และประกาศแจ้งเตือน/
- การแฮชข้อมูล Low Entropy และเลขบัตรเครดิตในเอเชียแปซิฟิก/
การแฮชข้อมูล Low Entropy และเลขบัตรเครดิตในเอเชียแปซิฟิก
สารบัญ
นี่คือข้อเท็จจริงที่ทำให้อึดอัด: การแฮชไม่เท่ากับการปกป้อง คุณสามารถเก็บ SHA-256 hash ของเลขบัตรเครดิต ปฏิบัติตาม PCI DSS ครบถ้วน แต่ยังคง ไม่มีการปกป้อง อย่างมีนัยสำคัญ เพราะค่าที่คุณแฮชมี entropy ไม่มากพอที่จะต้านทาน brute force
เรื่องนี้ทำให้ทีมวิศวกรรมที่ระมัดระวังพลาดได้ง่าย เพราะการแฮช รู้สึก ปลอดภัย hash เป็นทางเดียว ต้นฉบับกู้กลับไม่ได้ด้วยการย้อนฟังก์ชัน ข้อมูลจึงต้องปลอดภัยสิ ปัญหาไม่ได้อยู่ที่ hash ปัญหาอยู่ที่สิ่งที่คุณป้อนเข้าไป
ปัญหา entropy ในตัวเลขจริง #
เลขบัตร 16 หลักไม่ได้สุ่ม โครงสร้างของมันเป็นสาธารณะและตายตัว:
- หลักที่ 1 ถึง 4-6 คือ Issuer Identification Number (IIN): รหัส prefix ของธนาคาร เป็นสาธารณะทั้งหมด
- หลักสุดท้าย คือ checksum คำนวณด้วย อัลกอริทึม Luhn ซึ่งเป็นสูตรที่เผยแพร่ตั้งแต่ปี 1954 มันไม่ใช่ความลับ มันคือการตรวจจับความผิดพลาด
ทีนี้ mask PAN ตามแบบที่ PCI DSS อนุญาตโดยทั่วไป: เห็น 4-6 หลักแรกและ 4 หลักท้าย ซ่อน 6-8 หลักตรงกลาง:
4532 AAXX XXXX 1234
เมื่อรู้ IIN แค่ 4 หลัก สิ่งที่ยังไม่รู้คือ 8 หลัก หรืออย่างมาก 100,000,000 ค่าที่เป็นไปได้ พอใช้ Luhn checksum คัดแล้วจะเหลือเพียง 1 ใน 10 พื้นที่ค้นหาจริงของคุณคือ 10 ล้านค่า นั่นไม่ใช่รหัสผ่าน นั่นคือรายการที่เล็กมาก
ทดสอบ 10 ล้าน hash ได้เร็วแค่ไหน? #
ตรงนี้แย่ลงไปอีก SHA-256 เร็ว โดยการออกแบบ มันถูกสร้างมาเพื่อตรวจความถูกต้องครบถ้วน ที่ความเร็วระดับกิกะบิต ไม่ใช่เพื่อเก็บความลับ benchmark การถอดด้วย GPU สมัยใหม่เป็นสาธารณะ และทำซ้ำได้:
| ฮาร์ดแวร์ | ความเร็ว SHA-256 โดยประมาณ |
|---|---|
| 1× RTX 4090 GPU | ~8.5 พันล้าน hash/วินาที |
| 4× RTX 4090 cluster | ~34 พันล้าน hash/วินาที |
| 8× RTX 4090 cluster | ~68 พันล้าน hash/วินาที |
สิบล้านครั้งหารด้วย 8.5 พันล้านต่อวินาที เท่ากับประมาณ หนึ่งในพันของวินาที บน GPU สำหรับผู้บริโภคตัวเดียว แม้แต่คอมพิวเตอร์ GPU ตัวเดียวก็ใช้ rainbow table เพื่อ “ถอด hash” เลขบัตรเครดิตได้ในพริบตา
ข้อสรุปนั้นตรงไปตรงมา: ผ่านการตรวจสอบไม่เท่ากับปลอดภัย สำหรับ field ที่มี entropy ต่ำ แม้แต่ SHA-2 (หรือ SHA-3) ก็ไม่ปลอดภัย แม้จะผ่านการตรวจสอบแล้ว ฟังก์ชันเป็นทางเดียวก็จริง แต่มัน ไล่จนหมด ได้ง่ายเมื่อพื้นที่ของ input เล็ก การเปลี่ยนจาก SHA-256 เป็น SHA-512 หรือ SHA-3 ไม่ช่วยอะไร เพราะมันเร็วพอ ๆ กัน
“ผ่านการตรวจสอบ” จริง ๆ แล้วอนุญาตอะไร #
PCI DSS ไม่ได้บอกให้คุณแฮช PAN ด้วย SHA-256 Requirement 3.5 กำหนดให้คุณทำให้ PAN อ่านไม่ออกด้วย cryptography ที่แข็งแกร่ง ซึ่งระบุอย่างชัดเจนถึง keyed hash และการเข้ารหัส และหมายเหตุว่า index ที่ แฮชและใส่ salt เป็นที่ยอมรับเมื่อ salt เป็นความลับ และ hash ไม่สามารถย้อนกลับได้ในทางปฏิบัติ ปัญหาคือ SHA-256 แบบเปล่า ๆ ไม่มี salt บนพื้นที่ 10 ล้านค่า ในทางปฏิบัติสามารถย้อนกลับได้ด้วยการไล่จนหมด จึงไม่ผ่าน เจตนารมณ์ ของข้อกำหนด แม้จะติ๊กถูกใน checklist ก็ตาม
การ mask (แสดง 4-6 หลักแรกและ/หรือ 4 หลักท้าย) เป็นมาตรการอีกแบบหนึ่ง: มันปกป้องสิ่งที่ พนักงานเห็น ไม่ใช่สิ่งที่คุณจัดเก็บ ทั้งสองอย่างสับสนได้ง่าย และความสับสนนี้เองคือที่มาของ PAN ที่ถูก mask แต่ถูกแฮชเปล่า ๆ ไปอยู่ใน production
ปกป้องข้อมูลแบบนี้อย่างไรให้ถูกต้อง #
ทางแก้คือปฏิบัติต่อ field ที่มี entropy ต่ำด้วยความเคารพแบบเดียวกับรหัสผ่าน เพราะในทางคณิตศาสตร์ มันอ่อนแอพอ ๆ กัน ตัวเลือกตามลำดับความเหมาะสม:
- ไม่เก็บมันเลย tokenise PAN แล้วเก็บเลขจริงไว้ใน vault หรือ HSM แยกต่างหาก ถ้าคุณไม่เก็บค่า ก็ไม่มีอะไรให้ brute force
- Keyed hashing (HMAC) พร้อม pepper ที่เป็นความลับ หากต้องทำ index ด้วย PAN ให้ใช้ HMAC ที่มี key entropy สูงเก็บไว้นอกฐานข้อมูล เมื่อไม่มี key brute force ก็เป็นไปไม่ได้ในทางคำนวณ ไม่ว่า entropy ของ input จะเป็นเท่าใด
- Memory-hard password hashing เมื่อต้องปกป้องค่าด้วยค่าของมันเอง ให้ใช้ Argon2id (RFC 9106) หรือ scrypt พร้อม random salt ต่อค่า และปรับพารามิเตอร์ให้การเดาแต่ละครั้งใช้เวลาและหน่วยความจำจริง Argon2id ที่ memory cost 64 MB เปลี่ยนการไล่จนหมด 0.001 วินาทีนั้นให้กลายเป็นเวลา GPU หลายเดือน
- Salt และ pepper ทุกที่ random salt ต่อค่าทำลาย rainbow table ที่คำนวณไว้ล่วงหน้า pepper ที่เป็นความลับทำลายการโจมตีแบบ offline ได้ทั้งหมดเมื่อมันยังเป็นความลับ
OWASP Password Storage Cheat Sheet และ NIST SP 800-63B ต่างแนะนำ memory-hard function สำหรับความลับที่มี entropy ต่ำด้วยเหตุผลเดียวกันนี้
บทเรียนที่นอกเหนือจากบัตร #
เรื่องนี้ใช้ได้กับตัวระบุรูปแบบตายตัวทุกชนิดที่มี entropy จำกัด: เลขบัตรประชาชน เบอร์โทรศัพท์ วันเกิด หรือแม้แต่ API key ที่สร้างมาไม่ดี หากพื้นที่ของ input เล็ก ความเร็วของ hash function คือศัตรูของคุณ และ “ผ่านการตรวจสอบ” ไม่ใช่คำพ้องของ “ปลอดภัย”
บริการ การตรวจสอบความมั่นคงปลอดภัยของ API และแอปพลิเคชัน ตรวจสอบว่าโค้ดของคุณจัดเก็บและส่งค่าละเอียดอ่อนอย่างไรจริง ๆ และเราจะบอกตรง ๆ ว่าจุดไหนที่การผ่าน checklist กำลังปล่อยให้ข้อมูลจริงถูกเปิดเผย