5 วิธีป้องกันการโดน Code Injection ใน JavaScript และ Node.js
21 พฤษภาคม 2021
โดยทั่วไปการเขียน Code จะมีเครื่องมือป้องกันภัยคุกคาม Code Injection ในระดับเบื้องต้น ซึ่งอาจจะมีช่องโหว่ หรือ ข้อบกพร่องบางอย่างที่ผู้ดูแลระบบอาจมองข้ามเช่น การเขียน Code ตามขั้นตอนอย่างถูกวิธี แต่คนอื่นอาจจะไม่ได้ทำตาม หรือ การใช้ Open Source Package ในแอปพลิเคชัน มาช่วยในการเขียน Code แต่เราจะมั่นใจได้อย่างไรว่า Code ที่สร้างจะมีความปลอดภัยอย่างเช่น ฟังก์ชัน eval() ฯลฯ ดังนั้นข้อบกพร่องต่าง ๆ ที่กล่าวมา อาจทำให้แฮกเกอร์เข้ามาควบคุมและแก้ไข Code เพื่อให้เกิดการ Injaction attack ได้นั่นเอง
Code Injecion คืออะไร?
Code Injection เป็นการโจมตีในรูปแบบ Injection attack โดยแฮกเกอร์สามารถส่ง JavaScript หรือ Node.js code มายัง Browser หรือ Node.js runtime จนเกิดข้อบกพร่องทำให้โปรแกรม interpreter (ตัวแปลคำสั่ง) ไม่สามารถแยกความแตกต่างของ trusted code ของผู้พัฒนา และ injected code (input) ของผู้โจมตีได้
หากต้องป้องกัน code injection ผู้ดูแลระบบควรทำอย่างไร
ผู้ดูแลระบบควรพิจารณาว่า Code ที่สร้าง มีหลักการ Secure Coding หรือไม่ เพราะ Secure Coding คือ วิธีการเขียนโค้ดให้ปลอดภัย ซึ่งมี 3 หลักการสำคัญ ๆ คือ
- ไม่อนุญาตให้มีการทำ Dynamic Code Execution ใด ๆ บนแอปพลิเคชัน หมายความว่าต้องหลีกเลี่ยงการใช้คำสั่งอย่างเช่น eval และ Code String ที่ส่งผ่านไปยัง setTimeout()
- Function ต่าง ๆ ควรหลีกเลี่ยง serialization ที่อาจเป็นช่องโหว่และนำไปสู่ injection attack ที่ Execute Code ใน serialization process ได้
- มีการสแกนแอปพลิเคชันให้แน่ใจว่าไม่มีความเสี่ยงต่อการโจมตีจาก Third-party Open Source Component
นอกจากนี้ หากใช้ Static Code Analysis Tool จะสามารถหาช่องโหว่ Code Injection ที่อาจเกิดขึ้นใน code ของเราหรือของเพื่อนร่วมงานได้ โดย Static Code Analysis Tool มี 5 วิธี ดังนี้
1.หลีกเลี่ยง eval(), setTimeout() และ setInterval()
โดยทั่วไป libraries (ชุดคำสั่งรหัส) ที่เป็นนิยมอย่าง eval (หรือ code construction ในรูปแบบอื่น) ก็อาจนำไปสู่ช่องโหว่ร้ายแรงได้ เพราะ ในขณะ JavaScript runtime ตัว Browser และ Server-side Node.js platform จะอนุญาตให้ Evaluated และ Executed Code ในระหว่าง run-time ด้วยเหตุนี้เหล่าโปรแกรมเมอร์จึงพยายามสร้าง Dynamic Way เพื่อเข้าถึงข้อมูลใน DOM ตัวอย่างเช่น getElementform ที่อาจถูกควบคุมโดยผู้ใช้เช่นเดียวกับตัวแปร elementId อีกทั้งยังเป็นวิธีที่ดีกว่าการใช้ eval ดังนั้นเราจึงควรหลีกเลี่ยง dynamic code ในลักษณะนี้ไม่ว่าอย่างไรก็ตาม เพราะบน Node.js นั้น คำสั่ง eval สามารถถูกใช้เพื่อเข้าถึงข้อมูลที่เฉพาะเจาะจงบนแอปพลิเคชันได้เช่นกัน ซึ่งมีพื้นฐานอยู่บน Dynamic Evaluation สำหรับคำสั่ง setTimeout() และ setInterval() บน JavaScript นั้นสามารถรับ Code Strings เพื่อเรียกดูค่าบางอย่างของ Object ได้ เช่น console.log เป็นต้น แต่สำหรับ Node.js นั้นจะไม่อนุญาตให้ใช้ตัวอักษร string
2.หลีกเลี่ยง new Function()
สำหรับ new Function นั้น จะอนุญาตให้ระบุ Function ที่เป็นตัวอักษร String เช่นเดียวกับ eval(), setTimeout() และ setInterval() ที่กล่าวถึงไปในข้อ 1 ซึ่งทำให้ User สามารถป้อนค่า input บางอย่างเข้าสู่ Function ได้
3.หลีกเลี่ยง Code Serialization ใน JavaScript
ใน JavaScript การทำ Serialization คือการเปลี่ยน Object ให้อยู่ในรูป byte Stream เพื่อส่งผ่าน Network ข้อมูลของ Object ที่เก็บอยู่ในรูป Serialized Object นั้นถ้าเปิดดูด้วย hex-editor จะสามารถจัดการข้อมูลนั้นได้อย่างรวดเร็วและสร้างกลับเป็น Object ได้
4.ใช้ Node.js Security Linter
โดยทั่วไปแล้วเครื่องมือที่ใช้เขียน JavaScript หรือ Node.js นั้นจะมีเครื่องมือพื้นฐานอย่าง Standardjs หรือ Eslint ที่ใช้ตรวจสอบ Code ที่เขียนได้ แต่ในมุม Security ก็มีเครื่องมือพื้นฐานที่ใช้ตรวจสอบ Code ที่เขียนอย่าง eslint-plugin-security ที่มี Rule สำหรับตรวจจับรูปแบบโค้ดที่ไม่ปลอดภัย เช่น detect-eval-with-expression ที่ตรวจจับการใช้ eval() กับ Expression หรือตัวอักษร String เป็นต้น
5.ใช้ static code analysis (SCA) tool เพื่อหาและแก้ไข code injection
Static code Analysis (SCA) เป็นเครื่องมือพื้นฐานที่ให้บริบทเพียงพอสำหรับบังคับใช้ Code Style และมีความยืดหยุ่นมากกว่า Node.js Security Linter ในการแก้ไขปัญหาด้านความปลอดภัย แต่มีข้อกังวลบางอย่างเกี่ยวกับ Node.js security linter อย่างเช่น eslint-plugin-security มีลักษณะดังนี้
- False positive: linter rules นั้นเป็นแบบพื้นฐานที่จะแจ้งเตือนทุก false positive อาจทำให้เกิดความสับสน
- Rules are too rigid: rule บางอย่างบน linter นั้นไม่สามารถบอกถึงชนิดของตัวแปรได้ซึ่งทำให้ linter แจ้งเตือนผิดพลาด
- Rules are too basic: rule มีจำนวนน้อยและใช้การตรวจจับที่ง่ายเกินไป ไม่มีการกำหนดบริบทที่มากพอสำหรับ data flow จริงๆจาก user input ไปยัง sensitive code เช่น command execution, SQL queries หรืออื่นๆ
นอกจาก 5 วิธีที่กล่าวมา ยังมีเครื่องมือที่สามารถแก้ไขช่องโหว่ในขณะที่เขียนโค้ดได้เหมือนกัน คือ Synk Code, Static Application Security Testing Tool (SAST) ซึ่ง Synk Code เป็นเครื่องมือที่อยู่บน GitHub ที่ผู้ใช้งานสามารถเพิ่ม Project ไปบน GitHubRepository แล้ว Snyk จะนำข้อมูลใน GitHub Repository ไปสแกนหาช่องโหว่ และแจ้งเตือนพร้อมคำอธิบายถึงปัญหาที่พบในโค้ดบรรทัดนั้น อีกทั้งยังสามารถใช้ตรวจสอบและจัดการกับ User input ก่อนที่จะเข้าสู่ Sensitive code ด้วย
จะเห็นได้ว่า มีวิธีป้องกันการเกิด code injection หลายรูปแบบ ขึ้นอยู่กับความถนัดของผู้ดูแลระบบ และลักษณะ Code ที่สร้าง หากผู้ดูแลระบบมีความกังวล หรือ ไม่แน่ใจในการตรวจสอบช่องโหว่ด้วยตัวเอง NT cyfence พร้อมให้บริการ Vulnerability Assessment บริการตรวจสอบช่องโหว่ของระบบ โดยเจ้าหน้าที่ผู้เชี่ยวชาญเข้าตรวจสอบหาช่องโหว่ ซึ่งมีทั้งรูปแบบการทดสอบทั้ง External Scan และ Internal Scan ทำให้สามารถแก้ไขปัญหาได้ตรงจุด รวดเร็ว และลดความเสี่ยงในการถูกโจมตี สามารถสอบถามรายละเอียดเพิ่มเติมได้ที่ NT Contact Center 1888 หรือ ทาง E-mail ได้ที่ https://www.cyfence.com/contact-us/
ที่มา: https://snyk.io/blog/5-ways-to-prevent-code-injection-in-javascript-and-node-js/ และ https://snyk.io/blog/serialization-and-deserialization-in-java/
บทความที่เกี่ยวข้อง