ตัวอย่างโค้ด PHP Device Cookies ป้องกันการโจมตีแบบ Brute-force

การโจมตีระบบผู้ใช้งาน หรือการแฮ็คผู้ใช้งานอย่างหนึ่งที่นิยมใช้กันมาก ก็คือการสุ่มโจมตีชื่อผู้ใช้และรหัสผ่าน หรือ brute-force attack. วิธีที่ผู้โจมตีใช้งานหลักๆโดยทั่วไปก็คือ ถ้าไม่รู้ชื่อผู้ใช้เลยก็เขียนโปรแกรมเดาสุ่มชื่อผ้ใช้และรหัสผ่าน, ถ้ารู้ชื่อผู้ใช้แล้วก็เขียนโปรแกรมเดาสุ่มรหัสผ่าน. การเดาสุ่มก็ใช้วิธีเดียวกับการสุ่มสร้างอักขระ (random string) โดยอาจเน้นรหัสผ่านที่เดาง่ายและนิยมใช้กันมาก เช่น 12345678, password เป็นต้น.

สำหรับวิธีป้องกันก็ทำได้หลายวิธี เช่น

  • การใช้ Captcha ให้กรอกอักษรที่ปรากฏบนภาพ แต่ข้อเสียก็คือสร้างความยุ่งยากให้ผู้ใช้ตัวจริง ยิ่งถ้าตัวอักษรอ่านยากเกินไปก็เดากันไม่ค่อยจะถูก.
  • การใช้ป้องกันการสุ่มโจมตีด้วย IP address แต่ข้อเสียก็คือถ้าเครื่องผู้ใช้นั้นกลายเป็นเครื่องซอมบี้ หรือเครื่องอื่นๆในเครือข่ายเดียวกัน เช่นผู้ใช้ 2 คนในร้านเน็ตคาเฟ่ คนหนึ่งกำลังเข้าสู่ระบบอย่างถูกต้อง เป็นผู้ใช้ตัวจริง อีกคนเป็นผู้โจมตีที่กำลังพยายามสุ่มโจมตี การแบนทั้ง IP อาจทำให้ผู้ใช้ตัวจริงในเครือข่ายนั้นใช้งานไม่ได้เลย กลายเป็น DoS attack ไป.
  • การใช้ป้องกันการสุ่มโจมตีด้วย Device cookies. วิธีนี้เป็นแนวความคิดที่ดีมาก ไม่ต้องอ่านตัวอักษรที่อ่านยากๆ, ไม่กระทบผู้ใช้ในระดับ IP หรือทั้งเครือข่าย, และไม่รบกวนผู้ใช้ตัวจริงอีกด้วย.

ขั้นตอนการทำงาน

สำหรับขั้นตอนการทำงาน ขออ้างอิงจากในเว็บไซต์ของ OWASP โดยตรง ซึ่งจะพยายามแปลเป็นไทยให้เข้าใจได้มากที่สุด แต่หากอ่านภาษาอังกฤษได้ แนะนำให้เปิดทางต้นฉบับดูจะดีที่สุด.

  • T - time period (ระยะเวลา)
  • N - max number of authentication attempts allowed during T (จำนวนที่พยายามเข้าสู่ระบบได้มากครั้งที่สุดภายในระยะเวลา T)
  • สัญญลักษณ์ ∎ คือสิ้นสุดขั้นตอน.

Entry point for authentication request (จุดเริ่มต้นของการร้องขอตรวจสอบ หรือ login)

  1. if the incoming request contains a device cookie (ถ้าเครื่องผู้เรียกมี device cookie อยู่แล้ว):
    1. validate device cookie (ตรวจสอบ device cookie)
    2. if device cookie is not valid then proceed to step 2. (ถ้า device cookie ไม่ถูกต้องให้ไปขั้นตอน 2.)
    3. if the device cookie is in the lockout list (ถ้า device cookie อยู่ในรายการติดล็อค)
      • reject authentication attempt (ปฏิเสธการตรวจสอบผู้ใช้ หรือ login)∎
    4. else (ถ้าอื่นๆ)
      • authenticate user (ตรวจสอบผู้ใช้ หรือ login)∎
  2. if authentication from untrusted clients is locked out for the specific user (ถ้าการตรวจสอบจากเครื่องผู้ใช้ที่ไม่น่าเชื่อถือซึ่งถูกล็อคจากผู้ใช้ที่กำหนด)
    • reject authentication attempt (ปฏิเสธการตรวจสอบผู้ใช้ หรือ login)∎
  3. else (ถ้าอื่นๆ)
    • authenticate user (ตรวจสอบผู้ใช้ หรือ login)∎

Authenticate user (ตรวจสอบผู้ใช้ หรือ login)

  1. check user credentials (ตรวจสอบชื่อผู้ใช้และรหัสผ่าน)
  2. if credentials are valid (ถ้าชื่อผู้ใช้และรหัสผ่านถูกต้อง)
    1. issue new device cookie to user’s client (เขียน device cookie ให้ผู้ใช้นั้น)
    2. proceed with authenticated user (ส่งต่อไปยังหน้าเข้าสู่ระบบเรียบร้อยแล้ว)
  3. else (ถ้าอื่นๆ)
    1. register failed authentication attempt (ลงทะเบียนว่าล้มเหลวในการเข้าสู่ระบบ)
    2. finish with failed user’s authentication (เสร็จการเข้าสู่ระบบแบบล้มเหลว)

Register failed authentication attempt (ลงทะเบียนว่าล้มเหลวในการเข้าสู่ระบบ)

  1. register a failed authentication attempt with following information: { user, time, device cookie (if present) }. (ลงทะเบียนว่าล้มเหลวในการเข้าสู่ระบบ ด้วยข้อมูลเหล่านี้: {ชื่อผู้ใช้, เวลา, device cookie (ถ้ามี)}.)
  2. depending on whether a valid device cookie is present in the request, count the number of failed authentication attempts within period T either for (ขึ้นอยู่กับ device cookie ที่ถูกต้องมีอยู่หรือไม่, นับจำนวนครั้งที่เข้าสู่ระบบล้มเหลวภายในเวลา T สำหรับ
    1. all untrusted clients (เครื่องผู้ใช้ที่ไม่น่าเชื่อถือทั้งหมด)
      or (หรือ)
    2. a specific device cookie (device cookie ที่กำหนดมาให้)
  3. if number of failed attempts within period T > N (ถ้าจำนวนล้มเหลวภายในเวลา T > N)
    1. if a valid device cookie is presented (ถ้า device cookie ที่ถูกต้องมีอยู่)
      • put the device cookie into the lockout list for device cookies until now+T (เอา device cookie นั้นไปอยู่ในรายการที่ถูกล็อค จนกระทั่งเวลาปัจจุบัน + T)
    2. else (ถ้าอื่นๆ)
      • lockout all authentication attempts for a specific user from all untrusted clients until now+T (ล็อคการเข้าสู่ระบบทั้งหมดสำหรับผู้ใช้ที่กำหนดจากเครื่องผู้ใช้ที่ไม่น่าเชื่อถือทั้งหมด จนกระทั่งเวลาปัจจุบัน + T)

Issue new device cookie to user’s client (เขียน device cookie ให้ผู้ใช้นั้น)

เขียน device cookie ให้ผู้ใช้นั้นโดยมีรายละเอียดอย่างเช่น LOGIN, NONCE, SIGNATURE รายละเอียดดังนี้

  • LOGIN อาจเป็นข้อมูลชื่อผู้ใช้หรือเลขไอดีของผู้ใช้
  • NONCE คือตัวเลขหรืออักขระสุ่ม
  • SIGNATURE คือลายเซ็นที่เข้ารหัสประกอบด้วย LOGIN, NONCE และ secret key โดยอาจใช้ hash_hmac
  • secret key คือกุญแจลับที่ใช้ในการเข้ารหัสและถอดรหัส

validate device cookie (ตรวจสอบ device cookie)

  1. ตรวจสอบว่ามีรูปแบบถูกต้องตามการเขียนที่อธิบายไว้ด้านบน
  2. ตรวจสอบ SIGNATURE เท่ากับการเข้ารหัสของ LOGIN, NONCE
  3. ตรวจสอบว่า LOGIN นั้นมีตัวตนจริงในฐานข้อมูล

Download

ดาวน์โหลด

จากโค้ดตัวอย่างที่จะดาวน์โหลด จะมีไฟล์ .sql ซึ่งจะสร้างตารางผู้ใช้ตัวอย่าง และตารางอื่นๆที่จำเป็นรวมทั้งหมด 3 ตาราง.

การติดตั้ง

  1. แตกไฟล์ทั้งหมดลงใน folder ที่เรียกผ่าน HTTP ได้ เช่น http://localhost.localhost/device-cookies-example
  2. สร้างฐานข้อมูลเปล่าๆขึ้นมา 1 ฐาน
  3. import .sql ที่ดาวน์โหลดไป
  4. แก้ไขข้อมูลฐานข้อมูลต่างๆในไฟล์ config.php ให้ถูกต้อง

การทดสอบ

  1. เปิดเว็บไปยังหน้าที่ติดตั้งตัวอย่าง โดยเรียกไปยังหน้า form.php
  2. เปิดเครื่องมือบนเว็บเบราเซอร์เพื่อแสดงคุกกี้ที่จะได้รับ
  3. กรอกอีเมล admin@localhost และรหัสผ่าน pass โดยให้ทดลองกรอกที่ผิดและถูกเพื่อดูว่าได้ device cookie มาอย่างไรเมื่อผิดและถูก. สามารถลบคุกกี้, ล้างค่าในฐานข้อมูล และทดลองได้เรื่อยๆ โดยอาจทดลองเป็นผู้โจมตีเพื่อดูว่าระบบป้องกันได้อย่างไร
  4. เรียกใช้หน้า cron.php เพื่อล้างค่าต่างๆเมื่อมันหมดอายุแล้ว

กระบวนการทำงานในการตรวจชื่อผู้ใช้และรหัสผ่านจะอยู่ในไฟล์ login.php และการทำงานของ device cookie ส่วนหนึ่งก็ถูกประยุกต์ใช้ร่วมกันในนั้น.

Source code ชุดนี้ทำแจกฟรีภายใต้การอนุญาตแบบ MIT ซึ่งให้อิสระในการนำไปแก้ไข ดัดแปลง หรือใช้งานได้ทุกจุดประสงค์.

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

คุณอาจใช้แท็กHTMLและแอททริบิวต์เหล่านี้: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>