เว็บแอพสมัยใหม่มีความท้าทายหลายอย่าง เรื่องความปลอดภัย (security) ก็เป็นเรื่องนึง และมันก็มักไม่ค่อยได้รับความใส่ใจนัก หรือไม่ก็ประเมินความสำคัญเอาไว้ต่ำเกินไป การทำ threat analysis หรือการวิเคราะห์ภัยคุกคามเป็นที่รู้จักกันมากขึ้นเนื่องจากเป็นสิ่งจำเป็นหากจะพัฒนาแอพจริงๆจังๆ และก็ยังมีพื้นฐานบางอย่างที่ไม่ว่ายังไงก็ตามนักพัฒนาควรจะรู้และทำได้
การจะเป็นนักพัฒนาในยุคนี้คุณจะต้องเป็นเหมือนมีดพกทหารสวิส (swiss army knife) นอกจากจะเขียนโปรแกรมได้ตาม requirement แล้ว ต้องทำให้เสร็จไว, ซอร์สโค้ดก็ต้องแก้ไขได้ง่าย มี test, มีความยืดหยุ่นแก้ไขเพิ่มเติมได้สำหรับความต้องการในอนาคต, จะต้องใส่ user interface (UI) ได้เอง, ทำ optimize database, เซตอัพ หรือทำ workflow การ deploy โปรแกรม
ทั้งหมดที่กล่าวมา เมื่อไหร่ก็ตามที่โปรแกรมถูกเอามาใช้งานจริง ถูกใครสักคน hack หรือเจาะระบบเมื่อนั้นแหละเรื่อง security ของระบบก็จะได้รับความสนใจขึ้นมา จริงๆแล้วมันก็เป็นเรื่องที่แอบอยู่กับโปรแกรมของเราตั้งแต่เริ่มพัฒนาแล้ว เรื่อง security นี่แหละ เป็นเรื่องที่สำคัญที่สุด
เค้าเปรียบเทียบ requirement ในด้าน security กับ performance เอาไว้ทำนองที่ว่า security เหมือน performance ตรงที่ เจ้าของโปรแกรมรู้ว่าต้องมี security แต่ไม่แน่ใจว่าจะวัดปริมาณมันยังไง มันไม่เหมือนกันตรงที่ถึงจะเห็นว่าโปรแกรมมี security แล้วแต่ก็ไม่แน่ใจอยู่ดีว่ามีมากพอรึยัง
นักพัฒนาสมัยใหม่อย่างเราต้องอัพเดตความรู้เหล่านี้กันบ้าง โปรแกรมของเราต้องมีภูมิคุ้มกัน ถ้ามีเวลามากหน่อยก็ควรจะไปหาตำรามาศึกษาให้ลึกๆ เลย ส่วน บทความ series นี้จะนำเสนอดังนี้
- ชี้ให้นักพัฒนารเห็นข้อผิดพลาดที่ผิดกันบ่อย ให้รู้ถึงความเสียงนั้นๆ
- แนะนำว่าจะจัดการ หรือหลีกเลี่ยงความเสี่ยงดังกล่าวได้อย่างไรบ้าง
(บทความต้นฉบับเป็น Evolving Publication คือเขียนตอนต่อๆไปที่ URL เดิม ตอนใหม่มาก็เพิ่มลงไปด้านล่างเรื่อยๆ)
เรื่องความปลอดภัยของ web application มีเนื้อหากว้างมาก ถึงแม้ว่าเราจะกำหนดขอบเขตว่าเป็นการใช้งานผ่าน browser เท่านั้นแล้วก็ตาม บทความนี้เหมาะกับคำว่า "ที่สุด" มากกว่าที่จะมารวบรวมทุกอย่างที่คุณควรจะรู้ แต่เรื่องที่เป็นที่สุดนี้ก็หวังว่าจะทำให้นักพัฒนาที่สนใจเรื่อง security เหมือนได้ก้าวใหญ่ๆ เข้ามาในเรื่องนี้
ความเชื่อใจ
ความเชื่อใจจัดว่าเป็นรากฐานของเรื่องความปลอดภัยเลย ลองนึกตามดูว่าเราจะเชื่อใจข้อมูลจากสถานการณ์เหล่านี้ได้หรือไม่
- เราเชื่อ request ที่ส่งมาจาก browser ของผู้ใช้ได้หรือไม่ (ตอบ ไม่ได้)
- เราเชื่อว่า service ที่จัดการกับ database ให้เรา จะทำข้อมูลไม่เสียหายและไม่สกปรกเลยใช่มั้ย (ตอบ ไม่เชื่อ)
- เชื่อใจได้มั้ยว่า connection ระหว่าง browser ของผู้ใช้มายังระบบของเราไม่โดนเจาะหรือแอบฟัง (ไม่)
- เราเชื่อใจใน service และฐานข้อมูลที่เราใช้ในระบบได้หรือเปล่า (ควรจะ)
เรื่อง security มันไม่ตรงไปตรงมาเราจะต้องหาทางรับมือกับมัน ให้มีความเสี่ยงน้อยที่สุด web application ที่อยากจะให้ปลอดภัยเสี่ยงต่ำ ควรจะต้องใช้ Threat Risk modeling แต่จะเอาไว้ตอนหน้า เรื่องมันค่อนข้างซับซ้อน
ตอนนี้จะมาดูกันว่าความเสี่ยงฯต่อระบบเรามีอะไรบ้าง
ปฎิเสธการรับ input ที่ผิดจาก form
อย่าคิดว่าการที่เราเลือกใช้ form input type ต่างๆในหน้าจอจะทำให้เราได้รับข้อมูลแบบที่เราต้องการได้อย่างถูกต้อง ถึงแม้ว่าจะมี javascript มาตรวจสอบก่อน submit ก็เถอะ การปลอมแปลงข้อมูลที่ส่งออกจาก browser ทำได้ไม่ยาก
input ที่เชื่อไม่ได้
หากจะวัดระดับความน่าเชื่อถือของข้อมูลที่ถูกส่งผ่าน html form จาก browser มายัง server และถึงแม้ว่าจะตรวจสอบด้วย javascript ก่อนส่งอีกด้วย ระดับความน่าเชื่อถือเป็น 0 การตรวจสอบความถูกต้องของข้อมูลต้องทำที่ server
ทำไมข้อมูลที่ผิดปกติหรือผิดธรรมดาของมันจึงเป็นเรื่องที่ต้องคิดถึงในแง่ความปลอดภัย จริงๆมันขึ้นอยู่กับ logic ของโปรแกรมเราด้วย แต่ข้อมูลที่ผิดธรรมดานั้นสามารถทำให้ผู้ประสงค์ร้ายโจมตีระบบเราได้ อาจจะทำให้ระบบทำงานผิดพลาด โดนล้วงเอาข้อมูล หรือรันโปรแกรมอะไรก็ได้ สิ่งที่นักพัฒนาจะทำได้ในข้อนี้คือการตรวจสอบข้อมูลเข้า (input validation)
การตรวจสอบข้อมูลเข้า
ทำเพื่อให้แน่ใจว่าเราได้ข้อมูลที่เป็นปกติ เป็นไปตามที่ระบบต้องการ การตรวจสอบนี้จะเป็นปราการด่านแรก การ check null หรือค่าว่างไม่เพียงพอ
positive validation หรือ whitlisting จำกัดรับแต่ข้อมูลที่ยอมรับได้เท่านั้น ให้นึกถึงว่า input นี้รับค่าอะไรได้บ้าง ถ้าเป็นตัวเลขอยู่ช่วงมากน้อยแค่ไหน ค่าบวก ค่าลบได้หรือไม่ การใส่ของลงตะกร้า e-commerce ก็ไม่น่าจะเป็น 1000 ชิ้น เป็นต้น
แล้วเมื่อตรวจพบความผิดปกติของข้อมูลจะทำอย่างได้บ้าง มีสองทางคือ แจ้ง error แล้วไม่บอกอะไรเลย กับบอกผู้ใช้ว่าข้อมูลส่วนไหนผิด แต่การบอกส่วนที่ผิดก็ต้องระมัดระวัง บอกแล้วทำให้รู้ถึงชื่อตัวแปรระบบก็ไม่ได้นะ ให้ใช้ประโยคกลางๆ บอกแค่ว่าข้อมูล field ไหนที่ยังไม่ถูก
เราอาจจะพยายามดักหรือหาข้อความที่เป็นอันตรายที่มากับข้อมูลที่รับเข้า แบบนี้เรียกกันว่า nagative validation หรือ blacklisting ปัญหาที่ตามมาหากใช้วิธีนี้ เราจะต้องเตรียมตรวจจับ bad input ให้ครบซึ่งมันจะเสียเวลาตรงนี้มาก เวลาผ่านไปอาจจะมีเทคนิคใหม่ๆ มาอีก
การพยายามกำจัดคำอันตรายออกจากข้อมูลนำเข้า เช่นหากเจอคำว่า <script>
ในข้อมูล ก็จะลบออกก่อนจะนำไปประมวลผลต่อ วิธีแบบนี้เรียก "sanitization" คนโจมตีอาจจะหาวิธีเลี่ยงเทคนิค sanitization ของเราได้ เช่น ใส่ <scr<script>ipt>
เมื่อลบคำว่า script ออกก็ยังมี tag script ติดมาอยู่ดี กลายเป็นว่าเราทำให้เกิดช่องโหว่ขึ้นจนได้
ถ้าต้องใช้เทคนิค blacklisting นี้ก็ต้องศึกษาให้ละเอียด เขียน test ดีๆ ศึกษาเอกสารนี้ให้เข้าใจ OWASP’s XSS Filter Evasion Cheat Sheet
web framework สมัยใหม่ส่วนใหญ่จะมี function ที่ทำหน้าที่ validation มาด้วยอยู่แล้ว หรือหากไม่มีเราก็สามารถไปหามาใช้ในรูปแบบ library เสริมก็ได้ การใช้ validation ที่มีให้เหล่านี้ทำให้เราเหมือนมีปราการป้องกัน ก่อนข้อมูลผิดปกติจะเข้าไปชั้นในระบบของเราได้
สรุป
- เลือกทำ Whitelist ถ้าทำได้
- ทำ Blacklist หากทำ Whitelist ไม่ได้
- ใส่ข้อจำกัดใน form input ให้ได้เยอะที่สุด
- เลี่ยงการตีข้อมูลใน input กลับมาให้ผู้ใช้เห็น
ปฎิเสธเนื้อหาจาก web ก่อนที่มันจะเข้าไปในส่วน logic ของระบบได้ โดยใช้ whitelist ที่มากับ web framework ที่เราใช้
แม้ว่าเนื้อหาข้างต้นจะพูดถึงแต่การตรวจสอบข้อมูลที่มาจาก form input หากเป็นเนื้อหาในรูปแบบอื่นเช่น json, xml codes ในส่วนที่ใช้ตรวจสอบ form input ก็สามารถใช้ตรวจสอบข้อมูลในรูปแบบอื่นดังกล่าวได้เช่นกัน
จำไว้ว่า
if you don't control it, you can't trust it. If it violates the contract, reject it!
~ ถ้าคุณไม่ได้ควบคุมมัน คุณเชื่อมันไม่ได้ ถ้ามันผิดไปจากข้อกำหนด โยนมันทิ้งไป
เรียบเรียงจาก Martin Fowler's The Basics of Web Application Security
โปรดติดตาม ตอนหน้าจะเป็นเรื่อง Encode HTML Output