ParitLAB
← Lab Notes

พัฒนาการและเวอร์ชัน · 2026-09-15

ป้องกันบอตในหน้าลืมรหัสผ่านโดยไม่เพิ่ม CAPTCHA ให้ผู้ใช้

เผยแพร่โดย ParitLAB
บันทึกจากการออกแบบ พัฒนา และทดสอบผลิตภัณฑ์ของเรา

Security, Password Reset, Rate Limiting, PHP

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

ตอนปรับระบบของ ParitLAB เราตั้งเป้าหมายสองข้อพร้อมกัน: ลดคำขออัตโนมัติ และรักษาประสบการณ์ของคนที่ลืมรหัสผ่านจริง เราจึงเลือกการป้องกันหลายชั้นที่ทำงานอยู่เบื้องหลัง แทนการให้ผู้ใช้ทุกคนแก้ภาพหรือกดช่อง CAPTCHA

ชั้นที่ 1: ช่อง honeypot สำหรับโปรแกรมกรอกฟอร์ม

ฟอร์มมีช่องชื่อเว็บไซต์ที่ถูกซ่อนจากหน้าจอและข้ามจากลำดับการกด Tab คนปกติจะไม่เห็นและไม่กรอก แต่บอตแบบง่ายที่เติมทุกช่องมักใส่ข้อมูลลงไป เมื่อเซิร์ฟเวอร์พบว่าช่องนี้มีค่า คำขอจะถูกปฏิเสธก่อนค้นหาบัญชีหรือส่งอีเมล

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

ชั้นที่ 2: ตรวจเวลาที่ใช้กรอกฟอร์ม

เมื่อเซิร์ฟเวอร์แสดงหน้าแบบฟอร์ม ระบบบันทึกเวลาไว้ใน session หากฟอร์มถูกส่งกลับมาเร็วกว่า 3 วินาที เราถือว่าไม่น่าใช่การพิมพ์โดยคนและหยุดคำขอนั้น วิธีนี้จัดการสคริปต์ที่ยิง POST ทันทีได้ดี โดยไม่ต้องเก็บข้อมูลส่วนตัวเพิ่ม

เราไม่ใช้เวลาขั้นต่ำเป็นหลักฐานเพียงอย่างเดียว เพราะผู้จัดการรหัสผ่านหรือเบราว์เซอร์สามารถกรอกอีเมลได้เร็ว และผู้โจมตีสามารถหน่วงเวลาได้ การตัดสินใจจึงต้องอาศัยชั้นถัดไปด้วย

ชั้นที่ 3: rate limit ที่ยังอยู่หลังรีสตาร์ต

ทุกคำขอที่ผ่านการตรวจเบื้องต้นจะถูกนับในฐานข้อมูล โดยเก็บค่าแฮชของ IP และอีเมลแทนข้อความต้นฉบับ ระบบอนุญาตไม่เกิน 10 ครั้งต่อ IP ต่อชั่วโมง และไม่เกิน 3 ครั้งต่อบัญชีต่อชั่วโมง ข้อมูลนับที่เก่ากว่า 24 ชั่วโมงจะถูกล้างออกระหว่างการทำงาน

การเก็บตัวนับในฐานข้อมูลสำคัญกว่าการเก็บในตัวแปรของโปรเซส เพราะเว็บไซต์ PHP อาจมีหลาย worker และโปรเซสเริ่มใหม่ได้ตลอด การล็อกและ transaction ทำให้คำขอพร้อมกันไม่สามารถผ่านช่องว่างจากการอ่านตัวนับเวลาเดียวกันได้ง่าย ๆ

อย่าเปิดเผยว่าบัญชีมีอยู่จริงหรือไม่

ไม่ว่าระบบจะพบอีเมล ถูกจำกัด หรือถูก honeypot จับ หน้าเว็บจะแสดงผลลัพธ์ทั่วไปแบบเดียวกัน หลักการนี้ลด account enumeration ซึ่งเป็นการลองรายชื่ออีเมลเพื่อค้นหาผู้ใช้ของระบบ การส่งอีเมลจะเกิดขึ้นเฉพาะเมื่อคำขอผ่านทุกชั้นและพบบัญชีเท่านั้น

สิ่งที่เราทดสอบ

ข้อจำกัดและสิ่งที่ต้องติดตาม

rate limit อาจกระทบผู้ใช้หลายคนที่ออกอินเทอร์เน็ตผ่าน IP เดียวกัน และผู้โจมตีที่กระจายหลาย IP ยังสามารถหลบขีดจำกัดต่อ IP ได้ เราจึงตั้งค่าให้พอรองรับการใช้งานปกติ และควรติดตามอัตราการบล็อก ปริมาณอีเมล และข้อร้องเรียนจริง หากรูปแบบการโจมตีเปลี่ยน ค่อยเพิ่มมาตรการที่เหมาะสม เช่น proof-of-work หรือ CAPTCHA เฉพาะคำขอที่มีความเสี่ยง แทนการเพิ่มภาระให้ทุกคนตั้งแต่แรก