รหัสผ่านหลุดจาก Phishing แล้วยังไงต่อ — หยุด Credential Stuffing ที่หน้าเว็บ
รหัสผ่านที่หลุดจาก phishing ถูกนำกลับมายิงซ้ำที่หน้า login ของคุณ ดูว่า rate limiting ใน WAF หยุด credential stuffing ได้แค่ไหน และตรงไหนที่ต้องใช้ MFA
รหัสผ่านหลุดจาก Phishing แล้วยังไงต่อ — หยุด Credential Stuffing ที่หน้าเว็บ
พนักงานคนหนึ่งกดลิงก์ในอีเมลปลอม กรอกอีเมลกับรหัสผ่านลงในหน้าที่หน้าตาเหมือนหน้า login ของบริษัททุกอย่าง ทีม IT รู้ตัวภายในไม่กี่ชั่วโมง สั่งรีเซ็ตรหัสผ่านบัญชีนั้น แจ้งเตือนทุกคนในองค์กร ปิดเคส
แล้วอีกสามเดือนต่อมา เว็บขายของออนไลน์ของบริษัทเริ่มมี login ล้มเหลวเป็นพันครั้งต่อวัน
รหัสผ่านชุดนั้นไม่ได้จบชีวิตตอนที่ถูกรีเซ็ต มันถูกส่งต่อ ขาย รวมเข้าไปใน combo list แล้วเอาไปลองซ้ำกับเว็บอื่นๆ ที่คนคนเดียวกันน่าจะใช้อยู่ ขั้นตอนนี้เรียกว่า credential stuffing และมันเกิดขึ้นที่หน้า login ของคุณ ไม่ใช่ในอีเมลของพนักงาน
ทำไมรหัสผ่านที่หลุดถึงกลับมาที่เว็บของคุณ
คนส่วนใหญ่ใช้รหัสผ่านซ้ำ นั่นคือสมมติฐานเดียวที่ทำให้ credential stuffing คุ้มค่าสำหรับคนโจมตี — ถ้ารหัสผ่านที่หลุดจากเว็บ A ใช้กับเว็บ B ได้ด้วยแม้จะแค่เปอร์เซ็นต์เล็กน้อย การยิงชุดข้อมูลหลายแสนรายการก็ยังได้บัญชีติดมือกลับไปอยู่ดี
เส้นทางมาตรฐานของรหัสผ่านหนึ่งชุดหลังหลุดจาก phishing:

จุดสำคัญคือ ช่วงเวลาระหว่างที่ข้อมูลหลุดกับที่มันถูกเอามาใช้ อาจห่างกันเป็นเดือนหรือเป็นปี การรีเซ็ตรหัสผ่านตอนเกิดเหตุจึงช่วยได้เฉพาะบัญชีที่คุณควบคุมอยู่ ส่วนบัญชีที่พนักงานคนนั้นใช้รหัสเดียวกันในเว็บอื่นๆ ไม่มีใครไปตามรีเซ็ตให้ และในทางกลับกัน ลูกค้าของคุณที่เคยโดน phishing จากที่อื่นก็กำลังพารหัสผ่านที่หลุดแล้วมาใช้กับเว็บคุณเหมือนกัน
ถ้าอยากรู้ว่าข้อมูลขององค์กรตัวเองโผล่อยู่ในแหล่งซื้อขายพวกนี้แล้วหรือยัง เรื่องนั้นเป็นงานของ dark web monitoring ซึ่งเป็นคนละด่านกับบทความนี้ — ด่านนี้คือ "ถ้ามันหลุดไปแล้วและกำลังถูกยิงกลับมา จะรับมือที่หน้าเว็บยังไง" ส่วนขั้นตอนตอบสนองตอนเพิ่งรู้ว่ามีคนโดน phishing อยู่ใน playbook รับมือ phishing
Credential stuffing หน้าตาไม่เหมือน "การโจมตี"
นี่คือสาเหตุที่มันหลุดรอดเครื่องมือหลายตัว
request ของ credential stuffing คือ HTTP POST ไปที่ /login พร้อมอีเมลที่ฟอร์แมตถูกต้องและรหัสผ่านที่ฟอร์แมตถูกต้อง ไม่มี SQL injection ไม่มี payload แปลกๆ ไม่มีอะไรให้ signature จับ มันคือคำขอ login ที่สมบูรณ์แบบทุกประการ เพียงแค่รหัสผ่านผิด
และคนที่ทำงานเป็นอาชีพก็ไม่ได้ยิงรัวจาก IP เดียว เขากระจายผ่าน proxy เยอะๆ ยิงช้าๆ สลับ user-agent สลับเวลา ให้แต่ละ IP ดูเหมือนคนธรรมดาที่พิมพ์รหัสผิดสองสามครั้ง
ดู request ทีละอันจึงไม่เจออะไรเลย ความผิดปกติมันไปโผล่ในภาพรวม — อัตราส่วน login สำเร็จต่อ login ล้มเหลวที่เพี้ยนไปจากเดิม, จำนวนอีเมลที่ไม่ซ้ำกันเลยจาก IP เดียว, หรือ 401 ที่พุ่งขึ้นเฉพาะ endpoint เดียวโดยที่ทราฟฟิกรวมของเว็บนิ่งเหมือนเดิม นี่คือชั้นที่ WAF เข้ามาช่วยดูได้ เพราะเป็นจุดที่เห็น request ของ login ทุกอันก่อนถึงตัว application (ถ้ายังไม่คุ้นว่า WAF ทำอะไรได้บ้าง อ่าน WAF คืออะไร ก่อนได้)
ในหน้าจอจริงเป็นแบบไหน
หน้า Rate Limiting ใน zcrWAF (อยู่ใต้เมนู Rules ร่วมกับแท็บ Custom Rules, Alert Rules และ IP Groups) มีสวิตช์อยู่สองตัวที่เกี่ยวกับเรื่องนี้โดยตรง และทั้งสองตัวเปิดใช้งานอยู่ในเดโม
Visit Limit — คำอธิบายบนหน้าจอเขียนว่า "Limit requests from a single IP within a time window to prevent high frequency access" ค่าในเดโมคือ Trigger Threshold 1200 REQ และ Block Duration 300 SEC
ตรงนี้ต้องอ่านป้ายกำกับให้ละเอียด: 300 วินาทีคือ ระยะเวลาที่บล็อก ไม่ใช่ความยาวหน้าต่างเวลาที่ใช้นับ 1,200 ครั้ง ตัวหน้าต่างเวลานั้นเป็นของอีกค่าหนึ่งที่ซ่อนอยู่ใต้ Show Advanced Options ซึ่งเดโมไม่ได้กางให้ดู แปลว่าจากหน้าจอนี้ เรายังไม่รู้ว่า 1,200 ครั้งนับกันในกรอบเวลาเท่าไร และคิดเป็นอัตราต่อวินาทีเท่าไรไม่ได้
Attack Limit — เขียนว่า "Limit attacks from a single IP within a time window to prevent repeat attacks" ตั้งไว้เข้มกว่ามาก คือ 20 REQ แล้วบล็อก 900 SEC (15 นาที)
ทีนี้ลองเอาสองค่านี้ไปวางทับกับพฤติกรรม credential stuffing ที่อธิบายไปข้างบน:
- ทั้งคู่นับ "จาก IP เดียว" ตามคำอธิบายบนหน้าจอ นั่นคือหัวใจของเรื่อง — ต่อให้ยังไม่รู้ความยาวหน้าต่างเวลา เพดาน 1,200 ครั้ง ต่อหนึ่ง IP ก็เป็นเพดานที่สูงมากสำหรับหน้า login และ bot ที่กระจายการยิงออกไปหลายสิบ IP ก็ไม่มี IP ไหนเข้าใกล้ตัวเลขนั้นเลย ไม่ว่าหน้าต่างเวลาจะยาวแค่ไหนก็ตาม
- Attack Limit ตามคำอธิบายของมันเอง นับเฉพาะสิ่งที่ระบบ จัดว่าเป็นการโจมตีไปแล้ว แต่ login POST ที่มีอีเมลถูกฟอร์แมตและรหัสผ่านถูกฟอร์แมต ไม่เข้าข่ายรูปแบบการโจมตีตั้งแต่แรก โอกาสที่มันจะถูกนับเข้าโควตา 20 ครั้งนั้นจึงมีน้อยมาก
พูดง่ายๆ คือสวิตช์สองตัวนี้เล็งไปที่สิ่งที่มันถูกออกแบบมาให้จับ — การยิงถี่จาก IP เดียว และการโจมตีที่ยืนยันรูปแบบได้แล้ว — ส่วน credential stuffing ที่ทำอย่างตั้งใจนั้นตั้งใจหลบทั้งสองเงื่อนไขนี้พอดี
อีกอย่างที่เห็นได้จากหน้าจอนี้คือ ไม่มีช่องให้ระบุ endpoint เลย ค่าที่ตั้งเป็นค่าระดับไซต์ทั้งก้อน ไม่ได้แยกว่าเป็น /login หรือหน้าอื่น ถ้าอยากได้กฎที่เข้มเฉพาะหน้า login แยกจากค่าเริ่มต้นของทั้งไซต์ แท็บที่ควรไปดูต่อคือ Custom Rules และ IP Groups ที่อยู่ข้างกัน คู่กับ Alert Rules ถ้าต้องการให้มีสัญญาณส่งออกมาแทนที่จะบล็อกเงียบๆ
และสังเกตว่ามีตัวเลือกไซต์อยู่บนหัวหน้าจอ แปลว่าตั้งค่าแยกกันได้รายไซต์ ซึ่งเป็นเรื่องดี เพราะเว็บที่มีหน้า login ของลูกค้าควรตั้งเข้มกว่าเว็บแนะนำบริษัทที่ไม่มีใครต้อง login เข้าไปเลย
ถ้าอยากดูภาพรวมว่ากลไก rate limiting ทั้งชุดมีอะไรบ้างและตั้งค่ายังไงไม่ให้บล็อกผู้ใช้จริง เขียนไว้แยกอีกบทความที่ ป้องกัน Bot และ DDoS Layer 7 ด้วย WAF — บทความนี้เจาะเฉพาะเคส replay หลังรหัสผ่านหลุดแล้ว
ของจริง: WAF หยุดอะไรได้ หยุดอะไรไม่ได้
| สถานการณ์ | WAF ช่วยได้แค่ไหน |
|---|
| ยิงชุดรหัสผ่านรัวๆ จาก IP เดียว | เป็นงานของ Visit Limit — จะตัดได้จริงหรือไม่ ยังขึ้นกับความยาวหน้าต่างเวลาที่ซ่อนอยู่ใน Advanced Options ส่วน Attack Limit ยังไม่นับให้อยู่ดี เพราะต่อให้ยิงเร็วแค่ไหน มันก็ยังเป็น login POST ที่ฟอร์แมตถูกต้อง |
| ยิงช้าๆ กระจายหลาย IP ผ่าน proxy | เพดานต่อ IP ไม่ช่วย ต้องอาศัยกฎที่ผูกกับ endpoint login โดยเฉพาะ ส่วนการ "มองเห็น" ต้องไปดูจากฝั่ง log และรายงาน ไม่ใช่จากหน้าตั้งค่านี้ |
| รหัสผ่านที่ยิงมาถูกต้องจริง | หยุดไม่ได้ — สำหรับ WAF มันคือ login ที่สำเร็จตามปกติ |
| บัญชีเดียวกันถูก login สำเร็จจากคนละประเทศห่างกันไม่กี่นาที | อยู่นอกขอบเขต WAF ต้องดูจากฝั่ง log/SIEM หรือระบบ identity |
ช่องสุดท้ายคือช่องที่ต้องพูดให้ชัด: rate limiting ไม่ได้ทำให้รหัสผ่านที่ถูกขโมยไปเลิกใช้งานได้ มันทำให้การเดาต้องใช้เวลานานขึ้น ใช้ IP มากขึ้น แพงขึ้น และทิ้งร่องรอยให้เห็นมากขึ้น เท่านั้น ตัวที่ตัดปัญหาจริงๆ ที่ชั้น identity คือ MFA — ซึ่ง zcrWAF ไม่ได้ทำให้ นั่นเป็นงานของระบบ authentication ที่คุณใช้อยู่ ใครที่บอกคุณว่า WAF ตัวเดียวจบเรื่อง credential stuffing ได้ คนนั้นกำลังขายเกินจริง
วิธีที่ถูกต้องคือมองเป็นสองด่านคู่กัน: MFA ตัดโอกาสที่รหัสผ่านถูกๆ จะใช้ได้จริง ส่วน WAF ทำให้ขั้นตอน "ลองไปเรื่อยๆ จนกว่าจะเจอ" มีต้นทุนสูงจนไม่คุ้ม และทำให้คุณเห็นตั้งแต่ตอนที่เขายังลองอยู่
สัญญาณว่าเรื่องนี้เกี่ยวกับคุณ
- กราฟ login ล้มเหลว (401/403) พุ่งขึ้นเป็นช่วงๆ ทั้งที่ยอดทราฟฟิกรวมของเว็บไม่ได้เปลี่ยน
- มี login สำเร็จจากประเทศหรือช่วงเวลาที่ลูกค้ากลุ่มปกติของคุณไม่น่าจะใช้งาน
- เพิ่งมีเคส phishing ในองค์กรและรีเซ็ตเฉพาะบัญชีที่โดน โดยไม่ได้บังคับเปลี่ยนบัญชีอื่นที่พนักงานคนนั้นใช้รหัสเดียวกัน
- หน้า login ของลูกค้ายังไม่มี MFA และไม่มีการจำกัดจำนวนครั้งที่กรอกผิดต่อบัญชี
- ตอบไม่ได้ว่าเดือนที่แล้วมีความพยายาม login ล้มเหลวกี่ครั้ง เพราะไม่มีใครดูตัวเลขนั้นอยู่
ข้อสุดท้ายเจอบ่อยที่สุด และแก้ง่ายที่สุด — เพราะข้อมูลมีอยู่แล้วในระบบ แค่ไม่มีใครตั้งให้มันส่งสัญญาณออกมา
zcrWAF เข้ามาช่วยตรงไหน
zcrWAF วางตัวอยู่หน้า application จึงเห็นทุก request ที่วิ่งเข้าหน้า login ก่อนถึงตัวเว็บ หน้า Rules รวมสี่แท็บไว้ในที่เดียว — Rate Limiting, Custom Rules, IP Groups และ Alert Rules — ซึ่งเป็นชุดที่ควรไล่ดูตามลำดับเวลาจะวางกฎเฉพาะสำหรับหน้า login แทนที่จะพึ่งค่าเริ่มต้นระดับไซต์อย่างเดียว
สิ่งที่ zcrWAF ไม่ได้ทำคือ MFA และการยืนยันตัวตน — ตรงนั้นยังต้องอยู่กับระบบ identity ของคุณเหมือนเดิม ถ้ายังไม่แน่ใจว่าเว็บที่ดูแลอยู่ควรเริ่มจากด่านไหนก่อน ลองดู แพ็กเกจ zcrWAF
ติดต่อทีมงาน
อยากรู้ว่าหน้า login ของเว็บที่ดูแลอยู่มีความพยายามยิงรหัสผ่านเข้ามามากแค่ไหน ทีมงานยินดีให้คำปรึกษาฟรี ไม่มีค่าใช้จ่าย
แหล่งข้อมูลอ้างอิง
- OWASP — Credential Stuffing — นิยามและกลไกของ credential stuffing ตรงกับที่อธิบายในบทความ: การยิงคู่ username/password ที่หลุดมาแบบอัตโนมัติ โดยอาศัยพฤติกรรมใช้รหัสผ่านซ้ำของผู้ใช้
- OWASP — Credential Stuffing Prevention Cheat Sheet — ระบุ MFA เป็นมาตรการป้องกันหลัก ตรงกับข้อสรุปของบทความที่ว่า WAF ทำให้การยิงมีต้นทุนสูงขึ้น แต่ MFA คือสิ่งที่ตัดปัญหาที่ชั้น identity จริงๆ