บทความนี้กล่าวถึงวิธีทดสอบช่องโหว่ของ SQL injection และชี้ให้เห็นถึง Sourcecode ที่เป็นช่องโหว่ รวมถึงแนวทางในการป้องกันสำหรับผู้พัฒนาระบบ
ขั้นตอน (Steps)
ติดตั้งใช้งาน DVNA
- ติดตั้งได้จากบทความ How to install DVNA (Damn Vulnerable NodeJS Application) on MacOS
- สามารถเรียกใช้งานครั้งต่อไปโดยใช้คำสั่ง
docker ps -a sudo docker start dbcf5b9227c4 sudo docker start f284553da237
- ไปที่หน้า UserSearch http://127.0.0.1:9090/app/usersearch
การโจมตี SQL injection
- สามารถติดตามวิธีโจมตีรูปแบบต่าง ๆ ได้จากบทความ
- How to exploit the vulnerability of SQL injection (Manual)
- How to exploit the vulnerability of SQL injection (Manual) – 2: password attacks
- How to bypass authentication using SQLi
- How to extract data due to vulnerability of SQLi
- How to inject shell scrips via SQLi
- How to run SQLMAP (Kali) on Windows
- How to exploit SQLi using SQLMAP via TOR
- จากตัวอย่างการโจมตีแบบ Manual
root' union select null, concat(name,0x0a,password) from Users order by 1#
- โดยใช้ Tools
sqlmap -r /root/Desktop/sql.txt --dump User
การหาช่องโหว่บน Sourcecodes
- พยายามค้นหาหน้าจอสำหรับกรอกข้อมูลจากผู้ใช้ จากตัวอย่างเป็นรูปแบบการเขียนโปรแกรมแบบ MVC (Model View Conroller) ส่วนติดต่อผู้ใช้คือ Views จะพบว่าหน้าจอ User Search มีส่วนติดต่อผู้ใช้ใน File ชื่อ usersearch.ejs และในส่วนของ Form สำหรับการ Submit ข้อมูลโดย Method แบบ Post
- ไปที่โฟลเดอร์ Routes เพื่อหา Function ที่ Server ใช้ในการประมวลผลฟังก์ชัน usersearch พบฟังก์ชันชื่อ appHandler.userSearch
- ไปที่โฟลเดอร์ core (เป็นส่วนเชื่อมต่อ models ที่ติดต่อกับฐานข้อมูล) เพื่อหาฟังก์ชัน appHandler.userSearch พบว่าอยู่ในไฟล์ appHandler.js พบฟังก์ชัน userSearch ดังนี้
- จาก Sourcecode เราพบว่า โปรแกรมรับค่า {login} จากผู้ใช้ req.body.login ซึ่งผ่านหน้า Web browser แล้วนำไปต่อกับคำสั่ง SQL ที่ใช้. Query ข้อมูลจากฐานข้อมูลทันที ซึ่งทำให้ผู้ใช้สามารถเพิ่มคำสั่ง SQL ที่เป็นอันตรายได้
module.exports.userSearch = function (req, res) { var query = "SELECT name,id FROM Users WHERE login='" + req.body.login + "'"; db.sequelize.query(query, { model: db.User })
การป้องกันและแก้ไขปัญหา
- ใช้งาน Prepared Statements เช่น
function findItems(req, resp) { try { // Find the relevant items sequelize.query( "SELECT Desc FROM Items WHERE Desc like ?", { replacements: ['%'+req.params.snippet+'%'], type: sequelize.QueryTypes.SELECT } ) // Retrieve results .spread(function(results, metadata) { // Add results to response }); } catch { // Handle error } }
- การตรวจสอบข้อมูลนำเข้าผู้ใช้ สามารถใช้ Libary เช่น https://www.npmjs.com/package/validator ดังนี้
- การตรวจสอบรูปแบบ Field ก่อนนำไปประมวลผล
- การจัดรูปแบบของ Field รูปแบบ E-mail โทรศัพท์ วันที่ รหัสบัตรประชาชน
- รูปแบบของ Field เช่น ตัวเลขอย่างเดียว
- ขนาดของ Field เช่น ไม่เกิน 13 ตัวอักษรเป็นต้น
var validator = require('validator'); validator.isEmail('foo@bar.com'); true
- การกรองอักขระพิเศษก่อนนำไปจัดเก็บ
- การกรองอักขระพิเศษ เช่น ;
sanitizer description whitelist(input, chars) remove characters that do not appear in the whitelist. The characters are used in a RegExp and so you will need to escape some chars, e.g. whitelist(input, '\\[\\]')
.blacklist(input, chars) remove characters that appear in the blacklist. The characters are used in a RegExp and so you will need to escape some chars, e.g. blacklist(input, '\\[\\]')
.
- การกรองอักขระพิเศษ เช่น ;
- การตรวจสอบรูปแบบ Field ก่อนนำไปประมวลผล
อ้างอิง
- https://appsecco.com/books/dvna-developers-security-guide/solution/a1-injection.html
- https://www.sitepoint.com/node-js-mvc-application/
- https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb.html
- https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
- https://snyk.io/blog/sql-injection-orm-vulnerabilities/