ข้ามไปยังเนื้อหาหลัก
  1. บทวิเคราะห์และประกาศแจ้งเตือน/

การแฮชข้อมูล 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 ต่ำด้วยความเคารพแบบเดียวกับรหัสผ่าน เพราะในทางคณิตศาสตร์ มันอ่อนแอพอ ๆ กัน ตัวเลือกตามลำดับความเหมาะสม:

  1. ไม่เก็บมันเลย tokenise PAN แล้วเก็บเลขจริงไว้ใน vault หรือ HSM แยกต่างหาก ถ้าคุณไม่เก็บค่า ก็ไม่มีอะไรให้ brute force
  2. Keyed hashing (HMAC) พร้อม pepper ที่เป็นความลับ หากต้องทำ index ด้วย PAN ให้ใช้ HMAC ที่มี key entropy สูงเก็บไว้นอกฐานข้อมูล เมื่อไม่มี key brute force ก็เป็นไปไม่ได้ในทางคำนวณ ไม่ว่า entropy ของ input จะเป็นเท่าใด
  3. Memory-hard password hashing เมื่อต้องปกป้องค่าด้วยค่าของมันเอง ให้ใช้ Argon2id (RFC 9106) หรือ scrypt พร้อม random salt ต่อค่า และปรับพารามิเตอร์ให้การเดาแต่ละครั้งใช้เวลาและหน่วยความจำจริง Argon2id ที่ memory cost 64 MB เปลี่ยนการไล่จนหมด 0.001 วินาทีนั้นให้กลายเป็นเวลา GPU หลายเดือน
  4. Salt และ pepper ทุกที่ random salt ต่อค่าทำลาย rainbow table ที่คำนวณไว้ล่วงหน้า pepper ที่เป็นความลับทำลายการโจมตีแบบ offline ได้ทั้งหมดเมื่อมันยังเป็นความลับ

OWASP Password Storage Cheat Sheet และ NIST SP 800-63B ต่างแนะนำ memory-hard function สำหรับความลับที่มี entropy ต่ำด้วยเหตุผลเดียวกันนี้

flowchart TD A[PAN ถูกจัดเก็บ] --> B{ต้องใช้ทำ index ไหม?} B -- ไม่ --> C[Tokenise / vault / HSM] B -- ใช่ --> D{มี secret key ไหม?} D -- ใช่ --> E[HMAC พร้อม pepper] D -- ไม่ --> F[Argon2id / scrypt + salt] style C stroke:#10B981,stroke-width:2px style E stroke:#10B981,stroke-width:2px style F stroke:#10B981,stroke-width:2px

บทเรียนที่นอกเหนือจากบัตร #

เรื่องนี้ใช้ได้กับตัวระบุรูปแบบตายตัวทุกชนิดที่มี entropy จำกัด: เลขบัตรประชาชน เบอร์โทรศัพท์ วันเกิด หรือแม้แต่ API key ที่สร้างมาไม่ดี หากพื้นที่ของ input เล็ก ความเร็วของ hash function คือศัตรูของคุณ และ “ผ่านการตรวจสอบ” ไม่ใช่คำพ้องของ “ปลอดภัย”

กังวลว่าตอนนี้คุณปกป้อง PAN หรือตัวระบุอื่น ๆ อย่างไร? ติดต่อเพื่อรับการตรวจสอบแบบตรงไปตรงมา คุยได้ทาง LINE (@PureSecurity) หรืออีเมล (hello@puresecurity.com)

บริการ การตรวจสอบความมั่นคงปลอดภัยของ API และแอปพลิเคชัน ตรวจสอบว่าโค้ดของคุณจัดเก็บและส่งค่าละเอียดอ่อนอย่างไรจริง ๆ และเราจะบอกตรง ๆ ว่าจุดไหนที่การผ่าน checklist กำลังปล่อยให้ข้อมูลจริงถูกเปิดเผย