SQL Injection คืออะไรและจะป้องกันได้อย่างไรในแอปพลิเคชั่น PHP?

ดังนั้นคุณคิดว่าฐานข้อมูล SQL ของคุณมีประสิทธิภาพและปลอดภัยจากการทำลายในทันทีหรือไม่ การฉีด SQL ไม่เห็นด้วย!


ใช่มันเป็นการทำลายอย่างฉับพลันที่เรากำลังพูดถึงเพราะฉันไม่ต้องการเปิดบทความนี้ด้วยคำศัพท์อ่อนแอปกติของ“ การรักษาความปลอดภัยที่เข้มงวด” และ“ การป้องกันการเข้าถึงที่เป็นอันตราย” การฉีด SQL เป็นกลอุบายเก่า ๆ ในหนังสือที่ทุกคนนักพัฒนาทุกคนรู้ดีและรู้ดีถึงวิธีป้องกันมัน ยกเว้นช่วงเวลาหนึ่งที่แปลกเมื่อพวกเขาล้มลงและผลลัพธ์ที่ได้จะไม่มีอะไรเสียหาย.

ถ้าคุณรู้อยู่แล้วว่า SQL Injection คืออะไรคุณสามารถข้ามไปที่บทความครึ่งหลังได้ แต่สำหรับผู้ที่เพิ่งเริ่มต้นในด้านการพัฒนาเว็บไซต์และกำลังฝันที่จะรับตำแหน่งผู้อาวุโสมากขึ้นการแนะนำบางอย่างก็เป็นไปตามลำดับ.

SQL Injection คืออะไร?

กุญแจสำคัญในการทำความเข้าใจ SQL Injection อยู่ในชื่อ: SQL + Injection คำว่า “การฉีด” ที่นี่ไม่มีความหมายทางการแพทย์ใด ๆ แต่เป็นการใช้คำกริยา “ฉีด” คำสองคำนี้นำเสนอแนวคิดของการวาง SQL ลงในเว็บแอปพลิเคชัน.

ใส่ SQL ลงในเว็บแอปพลิเคชัน . . อืม . . นั่นไม่ใช่สิ่งที่เรากำลังทำอยู่หรือ ใช่ แต่เราไม่ต้องการให้ผู้โจมตีขับฐานข้อมูลของเรา มาทำความเข้าใจว่าด้วยความช่วยเหลือของตัวอย่าง.

สมมติว่าคุณกำลังสร้างเว็บไซต์ PHP ทั่วไปสำหรับร้านค้าอีคอมเมิร์ซในพื้นที่ดังนั้นคุณตัดสินใจที่จะเพิ่มแบบฟอร์มการติดต่อเช่นนี้:

ชื่อของคุณ

ข้อความของคุณ

และสมมติว่าไฟล์ send_message.php เก็บทุกอย่างไว้ในฐานข้อมูลเพื่อให้เจ้าของร้านสามารถอ่านข้อความของผู้ใช้ได้ในภายหลัง อาจมีรหัสเช่นนี้:

<?PHP

$ name = $ _POST [‘name’];
$ message = $ _POST [‘message’];

// ตรวจสอบว่าผู้ใช้รายนี้มีข้อความอยู่แล้ว
mysqli_query ($ conn, "SELECT * จากข้อความที่ชื่อ = $ name");

// รหัสอื่นที่นี่

ดังนั้นก่อนอื่นคุณลองดูว่าผู้ใช้รายนี้มีข้อความที่ยังไม่ได้อ่านอยู่หรือไม่ คิวรี SELECT * จากข้อความที่ชื่อ = $ ชื่อดูง่ายพอสมควร?

ไม่ถูกต้อง!

ในความบริสุทธิ์ของเราเราได้เปิดประตูเพื่อทำลายฐานข้อมูลของเราทันที เพื่อให้สิ่งนี้เกิดขึ้นผู้โจมตีจะต้องมีเงื่อนไขดังต่อไปนี้:

  • แอปพลิเคชันทำงานบนฐานข้อมูล SQL (วันนี้เกือบทุกแอปพลิเคชัน)
  • การเชื่อมต่อฐานข้อมูลปัจจุบันมีสิทธิ์ “แก้ไข” และ “ลบ” ในฐานข้อมูล
  • ชื่อของตารางที่สำคัญสามารถเดาได้

จุดที่สามหมายความว่าขณะนี้ผู้โจมตีทราบว่าคุณกำลังใช้งานร้านค้าอีคอมเมิร์ซอยู่คุณน่าจะจัดเก็บข้อมูลคำสั่งซื้อในตารางคำสั่งซื้อ อาวุธทั้งหมดนี้ผู้โจมตีต้องทำคือระบุชื่อ:

โจ; ตัดทอนคำสั่ง; ครับท่าน! มาดูกันว่าแบบสอบถามจะเป็นอย่างไรเมื่อถูกเรียกใช้งานโดยสคริปต์ PHP:

SELECT * จากข้อความที่ชื่อ = Joe; ตัดคำสั่งซื้อ;

โอเคส่วนแรกของการสืบค้นมีข้อผิดพลาดทางไวยากรณ์ (ไม่มีเครื่องหมายคำพูดล้อมรอบ“ โจ”) แต่เซมิโคลอนบังคับให้เครื่องยนต์ MySQL เริ่มตีความคำสั่งใหม่: การตัดคำสั่ง เช่นเดียวกับในการปัดครั้งเดียวประวัติการสั่งซื้อทั้งหมดจะหายไป!

เมื่อคุณรู้วิธีการทำงานของ SQL Injection แล้วก็ถึงเวลาที่จะดูวิธีหยุดมัน เงื่อนไขสองข้อที่ต้องทำให้สำเร็จสำหรับการฉีด SQL ที่ประสบความสำเร็จ ได้แก่ :

  1. สคริปต์ PHP ควรมีการแก้ไข / ลบสิทธิ์บนฐานข้อมูล ฉันคิดว่านี่เป็นเรื่องจริงสำหรับแอปพลิเคชันทั้งหมดและคุณจะไม่สามารถทำให้แอปพลิเคชันของคุณเป็นแบบอ่านอย่างเดียว ��และคาดเดาสิ่งที่แม้ว่าเราจะลบสิทธิ์การแก้ไขทั้งหมดการฉีด SQL ยังสามารถอนุญาตให้บางคนเรียกใช้คิวรี SELECT และดูฐานข้อมูลทั้งหมดรวมถึงข้อมูลที่ละเอียดอ่อนได้ กล่าวอีกนัยหนึ่งการลดระดับการเข้าถึงฐานข้อมูลไม่ทำงานและแอปพลิเคชันของคุณต้องการ.
  2. กำลังดำเนินการอินพุตของผู้ใช้ วิธีเดียวในการฉีด SQL สามารถทำงานได้คือเมื่อคุณรับข้อมูลจากผู้ใช้ อีกครั้งการหยุดอินพุตทั้งหมดสำหรับแอปพลิเคชันของคุณไม่สามารถทำได้เนื่องจากคุณกังวลเกี่ยวกับการฉีด SQL.

ป้องกันการฉีด SQL ใน PHP

ขณะนี้เนื่องจากการเชื่อมต่อฐานข้อมูลแบบสอบถามและอินพุตของผู้ใช้เป็นส่วนหนึ่งของชีวิตเราจะป้องกันการฉีด SQL ได้อย่างไร โชคดีที่มันค่อนข้างง่ายและมีสองวิธีในการทำ: 1) ฆ่าเชื้ออินพุตของผู้ใช้และ 2) ใช้คำสั่งที่เตรียมไว้.

ฆ่าเชื้ออินพุตผู้ใช้

หากคุณใช้ PHP เวอร์ชันเก่ากว่า (5.5 หรือต่ำกว่าและสิ่งนี้เกิดขึ้นมากมายกับโฮสติ้งที่ใช้ร่วมกัน) คุณควรเรียกใช้การป้อนข้อมูลของผู้ใช้ทั้งหมดผ่านฟังก์ชั่นที่เรียกว่า mysql_real_escape_string () โดยพื้นฐานแล้วมันจะลบอักขระพิเศษทั้งหมดในสตริงเพื่อให้สูญเสียความหมายเมื่อใช้โดยฐานข้อมูล.

ตัวอย่างเช่นหากคุณมีสตริงเช่นฉันเป็นสตริงผู้โจมตีสามารถใช้อักขระอัญประกาศเดี่ยว (‘) เพื่อจัดการคิวรีฐานข้อมูลที่สร้างขึ้นและทำให้เกิดการฉีด SQL การเรียกใช้ผ่าน mysql_real_escape_string () สร้างสตริงของ I \ ซึ่งเพิ่มเครื่องหมายแบ็กสแลชในเครื่องหมายคำพูดเดี่ยวเพื่อหนีออกมา เป็นผลให้ตอนนี้สตริงทั้งหมดได้รับการส่งผ่านเป็นสตริงที่ไม่เป็นอันตรายไปยังฐานข้อมูลแทนที่จะสามารถเข้าร่วมในการจัดการคิวรีได้.

มีข้อเสียเปรียบประการหนึ่งสำหรับวิธีนี้: เป็นเทคนิคที่เก่าแก่มาก ๆ ที่สอดคล้องกับรูปแบบการเข้าถึงฐานข้อมูลแบบเก่าใน PHP ในฐานะของ PHP 7 ฟังก์ชั่นนี้ไม่มีอยู่อีกต่อไปซึ่งนำเราไปสู่แนวทางแก้ไขปัญหาถัดไปของเรา.

ใช้งบเตรียม

งบเตรียมเป็นวิธีที่จะทำให้แบบสอบถามฐานข้อมูลปลอดภัยและเชื่อถือได้มากขึ้น แนวคิดคือแทนที่จะส่งแบบสอบถามดิบไปยังฐานข้อมูลเราจะบอกโครงสร้างฐานข้อมูลของแบบสอบถามที่เราจะส่งก่อน นี่คือสิ่งที่เราหมายถึงโดย “เตรียม” คำสั่ง เมื่อคำสั่งถูกเตรียมไว้เราจะส่งข้อมูลเป็นอินพุตแบบ parametrized เพื่อให้ฐานข้อมูลสามารถ “เติมช่องว่าง” โดยเสียบอินพุตกับโครงสร้างแบบสอบถามที่เราส่งไปก่อน สิ่งนี้จะกำจัดพลังงานพิเศษใด ๆ ที่อินพุตอาจทำให้พวกเขาถูกมองว่าเป็นเพียงตัวแปร (หรือเพย์โหลดถ้าคุณต้องการ) ในกระบวนการทั้งหมด ข้อความที่เตรียมไว้มีลักษณะดังนี้:

<?PHP
$ servername = "localhost";
$ ชื่อผู้ใช้ = "ชื่อผู้ใช้";
$ password = "รหัสผ่าน";
$ dbname = "myDB";

// สร้างการเชื่อมต่อ
$ conn = new mysqli ($ servername, $ username, $ password, $ dbname);

// ตรวจสอบการเชื่อมต่อ
ถ้า ($ conn->connect_error) {
ตาย("การเชื่อมต่อล้มเหลว: " . $ conn->connect_error);
}

// เตรียมตัวและผูกมัด
$ stmt = $ conn->เตรียมความพร้อม ("ใส่เข้าไปใน MyGuests (ชื่อ, นามสกุล, อีเมล) ค่านิยม (?,?,?)");
$ stmt->bind_param ("sss", $ firstname, $ lastname, $ email);

// ตั้งค่าพารามิเตอร์และดำเนินการ
$ firstname = "จอห์น";
$ lastname = "กวางตัวเมีย";
$ email = "[email protected]";
$ stmt->รัน ();

$ firstname = "แมรี่";
$ lastname = "Moe";
$ email = "[email protected]";
$ stmt->รัน ();

$ firstname = "จูลี่";
$ lastname = "Dooley";
$ email = "[email protected]";
$ stmt->รัน ();

เสียงสะท้อน "สร้างระเบียนใหม่สำเร็จแล้ว";

$ stmt->ปิด();
$ conn->ปิด();
?>

ฉันรู้ว่ากระบวนการฟังดูซับซ้อนโดยไม่จำเป็นหากคุณยังใหม่ต่อการจัดทำงบ แต่แนวคิดนั้นคุ้มค่ากับความพยายาม. ต่อไปนี้คือ เป็นการแนะนำที่ดีให้กับมัน.

สำหรับผู้ที่คุ้นเคยกับส่วนขยาย PDO ของ PHP และใช้เพื่อสร้างคำสั่งที่เตรียมไว้ฉันมีคำแนะนำเล็กน้อย.

คำเตือน: ระวังเมื่อตั้งค่า PDO

เมื่อใช้ PDO สำหรับการเข้าถึงฐานข้อมูลเราสามารถเข้าใจถึงความปลอดภัยได้ “ อืมฉันใช้ PDO ตอนนี้ฉันไม่จำเป็นต้องคิดอะไรอีกแล้ว” – นี่คือความคิดของเราโดยทั่วไป เป็นความจริงที่ว่า PDO (หรือ MySQLi เตรียมคำสั่ง) เพียงพอที่จะป้องกันการโจมตี SQL injection ทุกประเภท แต่คุณต้องระวังเมื่อทำการตั้งค่า เป็นเรื่องธรรมดาที่จะคัดลอกโค้ดจากบทช่วยสอนหรือจากโครงการก่อนหน้าและไปต่อ แต่การตั้งค่านี้สามารถยกเลิกทุกอย่างได้:

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES จริง);

สิ่งที่การตั้งค่านี้ทำคือการบอก PDO ให้เลียนแบบข้อความที่เตรียมไว้แทนที่จะใช้คุณลักษณะข้อความสั่งที่เตรียมไว้ของฐานข้อมูล ดังนั้น PHP จะส่งสตริงข้อความค้นหาอย่างง่ายไปยังฐานข้อมูลแม้ว่าโค้ดของคุณจะดูเหมือนว่ากำลังสร้างคำสั่งที่เตรียมไว้และตั้งค่าพารามิเตอร์และสิ่งเหล่านั้นทั้งหมด กล่าวอีกนัยหนึ่งคุณมีความเสี่ยงต่อการฉีด SQL เหมือน แต่ก่อน ��

วิธีแก้ปัญหาง่าย: ตรวจสอบให้แน่ใจว่าการจำลองนี้ถูกตั้งค่าเป็นเท็จ.

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES เท็จ);

ตอนนี้สคริปต์ PHP ถูกบังคับให้ใช้คำสั่งที่เตรียมไว้ในระดับฐานข้อมูลป้องกันการฉีด SQL ทุกประเภท.

การป้องกันการใช้ WAF

คุณรู้หรือไม่ว่าคุณสามารถปกป้องเว็บแอปพลิเคชันจากการฉีด SQL โดยใช้ WAF (ไฟร์วอลล์แอปพลิเคชันเว็บ)?

ไม่ใช่แค่การฉีด SQL แต่ยังมีช่องโหว่อื่น ๆ อีกมากมายเช่นเลเยอร์ 7 สคริปต์ข้ามการตรวจสอบที่ขาดการปลอมแปลงข้ามไซต์การเปิดเผยข้อมูลและอื่น ๆ คุณสามารถใช้โฮสต์ด้วยตนเองเช่น Mod Security หรือ Cloud-based ดังต่อไปนี้.

SQL injection และเฟรมเวิร์ค PHP ที่ทันสมัย

การฉีด SQL นั้นเป็นเรื่องธรรมดาง่ายจนน่าหงุดหงิดและอันตรายมากที่เฟรมเวิร์ค PHP เว็บที่ทันสมัยทั้งหมดมาพร้อมกับการตอบโต้ ตัวอย่างเช่นใน WordPress เรามี $ wpdb->ฟังก์ชั่นเตรียม () ในขณะที่ถ้าคุณใช้กรอบ MVC มันจะทำงานให้คุณและคุณไม่จำเป็นต้องคิดที่จะป้องกันการฉีด SQL เป็นเรื่องที่น่ารำคาญที่ใน WordPress คุณต้องเตรียมคำสั่งอย่างชัดเจน แต่เดี๋ยวก่อนมันคือ WordPress ที่เรากำลังพูดถึง ��

อย่างไรก็ตามประเด็นของฉันคือนักพัฒนาเว็บยุคใหม่ไม่จำเป็นต้องคิดถึงการฉีด SQL และทำให้พวกเขาไม่ได้ตระหนักถึงความเป็นไปได้ ดังนั้นแม้ว่าพวกเขาจะเปิดแบ็คดอร์หนึ่งไว้ในแอปพลิเคชันของพวกเขา (อาจเป็นพารามิเตอร์การค้นหา $ _GET และนิสัยเก่าของการไล่ล่าการค้นหาที่สกปรก) ผลลัพธ์อาจเป็นความหายนะ ดังนั้นจึงเป็นการดีกว่าที่จะใช้เวลาลึกลงไปในรากฐาน.

ข้อสรุป

การฉีด SQL เป็นการโจมตีที่น่ารังเกียจมากบนเว็บแอปพลิเคชัน แต่หลีกเลี่ยงได้ง่าย อย่างที่เราเห็นในบทความนี้ระวังเมื่อประมวลผลอินพุตของผู้ใช้ (โดยวิธีการฉีด SQL ไม่ได้เป็นเพียงภัยคุกคามที่นำมาใช้ในการจัดการผู้ใช้นำเข้า) และสอบถามฐานข้อมูลคือทั้งหมดที่มีไป ที่กล่าวว่าเราไม่ได้ทำงานในด้านความปลอดภัยของกรอบงานเว็บเสมอไปดังนั้นจึงควรระวังการโจมตีประเภทนี้และไม่ล้มลง.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map