ในคลาสของการโจมตีแบบฉีด การฉีด PHP SQL โจมตีได้โดดเด่นมาก เว็บไซต์ส่วนใหญ่มีความเสี่ยงต่อมัน จากการวิจัยพบว่ามากกว่า 50% ของการโจมตีเกิดขึ้นบนเว็บโดยใช้การฉีด SQL ในบทความนี้ เราจะพูดถึงวิธีดำเนินการฉีด SQL และวิธีที่เราจะป้องกันสิ่งนี้ในแอปพลิเคชัน PHP
การฉีด SQL (SQLi) คืออะไร
อันดับแรก ให้เราเข้าใจการฉีด SQL ฉีด SQL (SQLi) เป็นวิธีการที่แฮ็กเกอร์เปลี่ยนคำสั่ง SQL ที่ทำงานที่ส่วนหลังผ่านการปลอมแปลงคำสั่ง SQL ที่ดำเนินการ การฉีดรูปแบบดังกล่าวจะดำเนินการผ่านช่องป้อนข้อมูลของแบบฟอร์มและทำให้เกิดผลที่ตามมาร้ายแรงในฐานข้อมูล ในที่สุดก็นำไปสู่การเปิดเผยข้อมูลที่มีความละเอียดอ่อนสูงจากฐานข้อมูล เนื่องจากแฮ็กเกอร์สามารถควบคุมฐานข้อมูลผ่านการฉีดคำสั่ง SQL เขา/เธอจึงได้รับสิทธิ์ในการแทรก อัปเดต หรือแม้แต่ลบข้อมูลออกจากฐานข้อมูล
การโจมตีด้วยการฉีด SQL เกิดขึ้นเมื่อโค้ดไม่ได้เขียนในลักษณะที่ปลอดภัย ดูเหมือนว่าบางอันเขียนด้วยการเข้ารหัสที่ปลอดภัย แต่ยังคงเปิดทางให้ SQLi อยู่:
- การกรองอักขระช่องว่างและการจัดการประเภทไม่ถูกต้อง
- ส่งข้อมูลที่ไม่ได้ถูกสุขอนามัยและเข้ารหัสอย่างไม่เหมาะสมไปยังฐานข้อมูล
- การผสมรหัสและข้อมูล
- การใช้เครื่องหมายคำพูดเพื่อคั่นสตริง
กล่าวโดยสรุป เมื่อการป้อนข้อมูลของผู้ใช้ไม่ได้รับการตรวจสอบอย่างถูกต้อง จะทำให้ฐานข้อมูลตีความข้อมูลผู้ใช้อย่างประสงค์ร้าย หากข้อมูลของผู้ใช้ถูกดึงโดยตรงจากส่วนหน้าและแทรกลงในแบบสอบถาม ก็จะนำไปสู่การประนีประนอม
ปัญหาอีกประการหนึ่งที่นำไปสู่ SQLi ก็คือ ข้อผิดพลาดนั้นแสดงต่อผู้ใช้ซึ่งอาจถูกผู้ใช้ที่ประสงค์ร้ายนำไปใช้ในทางที่ผิด เพื่อรับรายละเอียดเกี่ยวกับประเภทและเวอร์ชันของฐานข้อมูล และปรับใช้ช่องโหว่ที่ทำให้เกิดการโจมตีด้วยการฉีด SQL
การฉีด PHP SQL คืออะไร
ตัวอย่างรหัสที่ไม่ปลอดภัย
มาทำความเข้าใจแนวคิดของการโจมตีด้วยการฉีด PHP SQL ด้วยความช่วยเหลือของโค้ด PHP ที่มีช่องโหว่ดังต่อไปนี้:
<?php
$username = $_POST[‘uname'];
$pass = $_POST[‘password'];
$sql = "SELECT * FROM user_table WHERE username='".$username."' AND userpwd='".$pass"';";
?>
โค้ดด้านบนยอมรับอินพุตของผู้ใช้โดยตรงโดยไม่มีการตรวจสอบ และแทรกลงในคิวรี SQL ที่จะรันบนฐานข้อมูลโดยตรง แฮ็กเกอร์ยังสามารถแทรกข้อความค้นหาแบบลอจิคัลที่จะส่งคืนผลลัพธ์ จริง เช่น หากตัวแปร $password ได้รับค่าเป็น ” หรือ '1'='1′ ค่าจะกลายเป็น 1=1 ซึ่งจะเป็นจริงเสมอ ในที่สุดสิ่งนี้จะนำไปสู่การเข้าสู่ระบบที่ประสบความสำเร็จซึ่งจะนำไปสู่การประนีประนอมด้านความปลอดภัยอย่างรุนแรง
นอกจากนี้ ให้พิจารณาสถานการณ์อื่นที่มีการแสดงข้อผิดพลาดต่อผู้ใช้
<?php
…
…
elseif($mysqli->error)
{
print($mysqli->error);
}
?>
ในสถานการณ์สมมตินี้ แทนที่จะพิมพ์บันทึกข้อผิดพลาดไปยังหน้าจอผู้ใช้ จะเป็นแนวทางปฏิบัติที่ดีกว่าในการเก็บฐานข้อมูลที่สามารถบันทึกบันทึกข้อผิดพลาดและนำไปใช้ในภายหลังเพื่อตรวจสอบจำนวนครั้งที่เว็บไซต์อยู่ภายใต้ SQLi .
ตัวอย่างรหัสรักษาความปลอดภัย
ตัวอย่างของการเข้ารหัสที่ปลอดภัยเพื่อหลีกเลี่ยง การฉีด PHP SQL สามารถตรวจสอบชื่อผู้ใช้และรหัสผ่านสำหรับข้อความค้นหาเชิงตรรกะในลักษณะดังต่อไปนี้:
<?php
Function checkUserInput($str)
{
return
str_replace(array("‘",""", "'", ‘"‘),array("‘","""'",""",$str));
}
$username = checkUserInput($_POST[‘uname']);
$pass = checkUserInput($_POST[‘password']);
?>
ในลักษณะนี้ ผู้ใช้สามารถตรวจสอบความถูกต้องของการป้อนข้อมูลก่อนที่จะผนวกเข้ากับแบบสอบถาม SQL อีกวิธีหนึ่งในการป้องกันการฉีด PHP SQL คือการใช้คำสั่งที่เตรียมไว้ (PHP Data Objects (PDO)) นี่เป็นแนวทางที่มีประสิทธิภาพซึ่งคำสั่ง SQL สามารถดำเนินการซ้ำ ๆ ได้ PDO มีวิธีการที่ทำให้การสืบค้นแบบกำหนดพารามิเตอร์ใช้งานง่าย นอกจากนี้ยังช่วยเพิ่มความสามารถในการอ่านและพกพาโค้ด และทำงานร่วมกับฐานข้อมูล MySQL ไม่เพียงเท่านั้น แต่ยังทำงานร่วมกับฐานข้อมูลประเภทอื่นๆ อีกด้วย PDO กำหนดส่วนที่จะถือว่าเป็นอินพุตของผู้ใช้และส่วนที่เหลือเป็นคำสั่งฐานข้อมูล
ตัวอย่างโค้ดสำหรับ PDO สำหรับฐานข้อมูล MySQL คือ:
//DB credentials
define(‘DB_HOST','localhost');
define(‘DB_USER','John_Reaper');
define(‘DB_PASS','[email protected]@$$w0rd$');
define(‘DB_NAME','users');
if(isset($_GET[‘id']))
{
$id = $_GET[‘id'];
if(is_numeric($id) == true)
{
try
{
$dbh = new PDO(‘DBHOST;DB_NAME','DB_USER','DB_PASS');
$dbh->setAttribute(PDO::AFTER_ERRMODE, PDO::ERRMODE_EXCEPTION);
$q = "SELECT username FROM users WHERE id = :id";
$sth = $dbh->prepare($q);
$sth->bindParam(‘:id',$id);
$sth->execute();
$sth->setFetchMode(PDO::FETCH_ASSOC);
$res = $sth->fetchColumn();
print(htmlentities($res));
$dbh = null;
}
catch(PDOException $e)
{
error_log(‘PDOException - ‘.$e->getMessage(),0);
http_response_code(500);
die(‘Connection to database unsuccessful');
}
}
else
{
http_response_code(400);
die(‘Error processing malformed request');
}
}
วิธีป้องกันการฉีด PHP SQL
ดังนั้น คุณสามารถรักษาความปลอดภัยเว็บไซต์ของคุณจากการแทรก SQL ได้โดยใช้แนวทางปฏิบัติที่ดีที่สุดดังต่อไปนี้:
- ตรวจสอบการป้อนข้อมูลของผู้ใช้ที่ส่วนหน้าโดยใช้ JavaScript หรือที่ส่วนหลังโดยใช้ PHP
- ไม่แสดงข้อผิดพลาดให้ผู้ใช้เห็น ให้บันทึกข้อผิดพลาดลงในไฟล์และทำให้ผู้โจมตีไม่สามารถเข้าถึงได้ นอกจากนี้ ข้อความแสดงข้อผิดพลาดที่แสดงต่อผู้ใช้ต้องเป็นข้อความทั่วไปและไม่เปิดเผยข้อมูลใดๆ เกี่ยวกับฐานข้อมูล
- การใช้เคียวรีแบบกำหนดพารามิเตอร์ซึ่งระบุส่วนของการสืบค้น SQL ที่ต้องถือเป็นอินพุตของผู้ใช้
- การนำกระบวนงานที่เก็บไว้ที่ไม่ได้ใช้ออกเนื่องจากสามารถใช้ประโยชน์ได้ง่ายและป้องกันการฉีด SQL
- ให้สิทธิ์ที่เหมาะสมแก่ผู้ใช้ที่เหมาะสมเพื่อหลีกเลี่ยงการประนีประนอมในกรณีที่ผู้โจมตีข้ามการตรวจสอบสิทธิ์
การป้องกันขั้นสูงสุดจาก PHP SQL Injection
การใช้ไฟร์วอลล์อย่าง Astra สามารถเพิ่มภูมิคุ้มกันให้กับ SQLi ได้ นอกจาก SQLi แล้ว Astra Security Suite ยังป้องกันเว็บไซต์จากการโจมตีมากกว่า 100+ รายการ ซึ่งบางรายการเป็นบอทที่ไม่ดี, XSS, CSRF เป็นต้น
เป็นที่ทราบกันดีว่าเครื่องสแกนมัลแวร์ของเราสแกนเว็บไซต์ได้ในเวลาไม่ถึง 10 นาที และใช้เวลาน้อยกว่า (<1 นาที) สำหรับการสแกนครั้งต่อไป ภายใต้ข้อเสนอการตรวจสอบความปลอดภัยและการทดสอบ Pentesting วิศวกรของ Astra จะสแกนโค้ดแต่ละบรรทัดด้วยตนเองเพื่อค้นหาและแก้ไขจุดอ่อนในเว็บไซต์ของคุณเพื่อทำให้การรักษาความปลอดภัยไม่สามารถเข้าถึงได้
ทดลองใช้ Astra วันนี้!