Screen Shot 2557-08-26 at 9.13.19 PM
ช่วงหลังๆ มานี้ ได้พูดคุยเกี่ยวกับการประยุกต์ใช้งานแนวคิด TDD ( Test Driven Development )
กับเรื่องความปลอดภัย ( Security ) ในระดับของ code ได้หรือไม่
ซึ่งผมก็ตอบไปแบบไม่ต้องคิดเลย ก็คือ ได้สิ … แต่ว่า

  • คุณสามารถคิด test case สำหรับการทดสอบได้หรือไม่
  • คุณสามารถรู้ expected result จาก input ที่กำหนดไว้ได้หรือไม่

ถ้าสามารถคิดได้ ก็จะสามารถนำแนวคิด TDD มาประยุกต์ได้นั่นเอง
ดังนั้น เราลองมาคิด และ ลงมือทำกันดีกว่า ( Think Before Doing/Act )

ก่อนอื่นต้องบอกก่อนว่า TDD เป็นแค่แนวคิดหนึ่งที่สามารถนำมาใช้เท่านั้น
ยังมีแนวคิดอื่นๆ อีกนะเออ

เริ่มต้นกันเลย

ถ้าจะนำแนวคิด TDD มาใช้แล้วนั้น คุณจะต้องรู้ก่อนว่ารูปแบบการโจมตีเป็นเช่นใด ( Known Threats )
ส่วนที่ไม่รู้ ( Unknown Threats ) นั้นช่วยไม่ได้นะครับ
ดังนั้น ก่อนอื่นเราต้องทำความเข้าใจรูปแบบการโจมตีแบบต่างๆ ก่อนเลย
ซึ่งแนะนำให้นักพัฒนาศึกษาจาก Top 10 OWASP  Proactive Control
แต่เชื่อเถอะว่ามันก็ยังไม่ครอบคลุมทั้งหมดหรอก
เพียงแต่ช่วยลดให้เหลือน้อยลงเท่านั้นเอง

แล้วขั้นตอนการนำ TDD มาใช้จะเป็นอย่างไร

  • เขียน test case เพื่อทำการตรวจสอบการโจมตี
  • พยายามหาวิธีการสำหรับการป้องกันการโจมตีที่กำหนดไว้ใน test case ว่ามันสามารถป้องกันได้
  • โดยทุกๆ  test case จะต้องทำงานผ่านตามที่คาดหวังไว้ใน test case ทุกๆ ตัว
    • ต้องผ่านทั้งการตรวจสอบเรื่องการโจมตี
    • ต้องผ่านทั้งการทำงานแบบปกติทั่วไป
  • TDD ช่วยทำให้เรารู้ปัญหาได้อย่างรวดเร็ว และก็ทำให้เราแก้ไขและหาวิธีการได้อย่างรวดเร็ว
  • TDD ช่วยทำให้เรามั่นใจใน code มากยิ่งขึ้น ว่าสามารถป้องกันการโจมตีที่เรารู้จักได้

โครงสร้างของการโจมตีระบบงาน

จะส่งผลกระทบต่อองค์กรและธุรกิจไม่มากก็น้อย
มีโครงสร้างและเส้นทางดังรูป

Screen Shot 2557-08-26 at 9.14.20 PM

ลองมาดูวิธีการเขียน TDD เพื่อทดสอบการโจมตีรูปแบบต่างๆ กัน

โดยผมจะใช้วิธีการโจมตีจาก Top 10 จาก OWASP  ดังนี้
ขอยกตัวอย่าง 2 กลุ่ม คือ

  1. SQL Injection
  2. Validate Input

1. SQL Injection

เป็นรูปแบบการยิงข้อมูลเข้ามาเพื่อโจมตีผ่าน SQL, NoSQL, OS, XML, XPATH และ LDAP เป็นต้น
โดยข้อมูลที่ส่งเข้ามานั้น เมื่อผ่านตัวแปลและประมวลผลแล้ว
จะส่งผลกระทบต่อระบบงาน เช่นการประมวลผลชุดคำสั่งที่ไม่ได้รับอนุญาติ

ตัวอย่างสุด classic คือ

  • การส่ง ‘or ‘1’=’1 เข้ามายังระบบ
  • ระบบงานไม่มีการตรวจสอบข้อมูลเข้า ใดๆ ทั้งสิ้น
  • แถมในการประมวลผลคำสั่ง SQL ก็เป็นแบบการเชื่อมต่อคำสั่ง SQL เช่น
String query = "SELECT * FROM person WHERE ID='" + request.getParameter("id") + "’";

การโจมตีนี้ส่งผลกระทบ
จะทำการดึงข้อมูลทั้งหมดในตาราง person
และจะยิ่งอันตรายกว่านั้น ถ้าทำการแก้ไขข้อมูล เรียก store procedure หรือไปสั่ง execute คำสั่งของ OS ต่อไป

แล้วเราจะนำ TDD เข้ามาช่วยอย่างไร ?
เริ่มง่ายๆ ด้วยการสร้าง test case เพื่อจำลองการโจมตีแบบ SQL Injection ขึ้นมาดังนี้

ข้อมูลเริ่มต้น เป็นดังนี้

  • กำหนดให้ข้อมูล person ทั้งหมดมี 5 คน
  • ผมทดสอบผ่าน In-Memory database ชื่อว่า H2 database

สามารถเขียน test case สำหรับการโจมตี code ที่สำเสร็จ ซึ่งจะต้องส่งข้อมลกัลมาจำนวน 5 คนดังนี้

เมื่อทุกอย่างทำงานผ่าน หมายถึง เราโจมตีได้สำเร็จ
ต่อจากนั้น ให้ทำการแก้ไขด้วยวิธีการที่ถูกต้องและเหมาะสม
สามารถเขียน test case ใหม่เพื่อตรวจสอบดูว่าต้องไม่พบข้อมูลของ person ดังนี้

ผลที่ได้คือ จะโยน exception DataNotFoundException ออกมา
นั่นหมายความว่า เราได้ทำการแก้ไขปัญหานี้ไปเรียบร้อย
และใน test case แรกจะต้องทำงานผิดพลาดนั่นเอง ดังรูป

Screen Shot 2557-08-26 at 9.50.48 PM

2. Validate Input

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

ข้อแนะนำสำหรับเรื่องนี้ก็คือ

  • อย่าเชื่อมั่นเฉพาะการ validate data ฝั่ง client เท่านั้นนะ ควรจะทำทั้ง client และ server เสมอ
  • ตรวจสอบด้วยการใช้ White list validation เพื่อระบุชนิดข้อมูลและขนาดของข้อมูลตามที่กำหนดไว้ รวมทั้งสามารถใช้ regular expression ร่วมได้

ในการ Validate Input นั้นส่วนใหญ่มักจะทำเป็น Utility class หรือกลุ่มของคลาสสำหรับการ Validate ข้อมูล
ซึ่งผลเขียนไว้ใน Blog เรื่อง หลีกเลี่ยงการใช้ IF ในการตรวจสอบข้อมูล
โดยสามารถเขียน test case ต่างๆ เพื่อเอาไว้ตรวจสอบข้อมูล

ในภาษา Java สามารถนำ Library ต่างๆ มาใช้งานได้ เช่น Apache Common Validator
รวมทั้งเครื่องมือต่างๆ จาก OWASP มาร่วมด้วย เช่น

TDD อย่างเดียวมันไม่พอหรอกนะ

ยังต้องใช้แนวคิด และ วิธีการอื่นๆ เข้าใาช่วยด้วย เช่น

  • การใช้งาน Coding Standard
  • การทำ Code Review
  • การทดสอบแบบ manual และ การใช้เครื่องมือตรวจสอบ

จำไว้ว่าไม่มีอะไรที่เป็น Silver Bullet นะครับ !!!
เพียงคุณเข้าใจมัน ก็สามารถนำมาแก้ไขปัญหาได้แล้ว