TL; DR
- แอปพลิเคชันยอมรับอินพุตในกรณีนี้ 'Nancy' โดยไม่ต้องพยายามฆ่าเชื้ออินพุตเช่นโดยการหลีกเลี่ยงอักขระพิเศษใน
โรงเรียน=> INSERT INTO VALUES ( 'Nancy' ) ของนักเรียน INSERT 0 1
- การฉีด SQL เกิดขึ้นเมื่อป้อนเข้าไปในคำสั่งฐานข้อมูลที่ถูกจัดการเพื่อ- ทำให้เซิร์ฟเวอร์ฐานข้อมูลเพื่อดำเนินการ
โรงเรียนSQL โดยพลการ=> INSERT INTO VALUES ( 'Robert' ) นักเรียน DROP ตารางนักเรียน; - '); INSERT 0 1 DROP ตาราง
- บันทึกของนักเรียนหายไปแล้ว - มันอาจจะแย่กว่านี้อีก!
โรงเรียน=> เลือก* จากนักเรียน;
ข้อผิดพลาด: ความสัมพันธ์"นักเรียน" ไม่ได้อยู่
บรรทัดที่1 : เลือก* จากนักเรียน; ^
สิ่งนี้จะลดลง (ลบ) ตารางนักเรียน
( ตัวอย่างรหัสทั้งหมดในคำตอบนี้ถูกเรียกใช้บนเซิร์ฟเวอร์ฐานข้อมูล PostgreSQL 9.1.2 )
เพื่อให้ชัดเจนว่ามีอะไรเกิดขึ้นลองทำตารางง่ายๆที่มีเฉพาะฟิลด์ชื่อและเพิ่มแถวเดียว:
โรงเรียน=> สร้างตารางนักเรียน( ชื่อ TEXT PRIMARY KEY );
ข้อสังเกต: CREATE TABLE / PRIMARY KEY จะสร้างนัยดัชนี"students_pkey" สำหรับตาราง"นักเรียน" CREATE TABLE
โรงเรียน=> INSERT INTO นักเรียนVALUES ( 'จอห์น' ); INSERT 0 1
สมมติว่าแอปพลิเคชันใช้ SQL ต่อไปนี้เพื่อแทรกข้อมูลลงในตาราง:
INSERT INTO VALUES นักเรียน( 'foobar' );
แทนที่foobar
ด้วยชื่อจริงของนักเรียน การดำเนินการแทรกปกติจะมีลักษณะเช่นนี้:
- การป้อนข้อมูล: แนนซี่
โรงเรียน=> INSERT INTO นักเรียนVALUES ( 'แนนซี่' ); INSERT 0 1
เมื่อเราสอบถามตารางเราจะได้สิ่งนี้:
โรงเรียน=> เลือก* จากนักเรียน;
ชื่อ
-------
จอห์น
แนนซี่
( 2 แถว)
เกิดอะไรขึ้นเมื่อเราใส่ชื่อ Little Bobby Tables ลงในตาราง
- อินพุต: Robert '); นักเรียน DROP Table -
โรงเรียน=> INSERT เข้าสู่นักเรียนค่า( 'โรเบิร์ต' ); DROP ตารางนักเรียน; - '); INSERT 0 1 DROP ตาราง
การฉีด SQL ที่นี่เป็นผลมาจากชื่อของนักเรียนที่ยกเลิกคำสั่งและรวมถึงDROP TABLE
คำสั่งแยกต่างหาก; เครื่องหมายขีดคั่นสองตัวที่ส่วนท้ายของอินพุตมีจุดประสงค์เพื่อใส่รหัสใด ๆ ที่เหลือซึ่งอาจทำให้เกิดข้อผิดพลาด บรรทัดสุดท้ายของการส่งออกยืนยันว่าเซิร์ฟเวอร์ฐานข้อมูลได้ลดลงตาราง
สิ่งสำคัญคือให้สังเกตว่าในระหว่างการINSERT
ดำเนินการแอปพลิเคชันไม่ได้ตรวจสอบอินพุตสำหรับอักขระพิเศษใด ๆ และดังนั้นจึงอนุญาตให้ป้อนข้อมูลโดยพลการเพื่อป้อนลงในคำสั่ง SQL ซึ่งหมายความว่าผู้ใช้ที่เป็นอันตรายสามารถแทรกเข้าไปในสนามตามปกติมีไว้สำหรับผู้ใช้ป้อนสัญลักษณ์พิเศษเช่นคำพูดพร้อมกับรหัส SQL โดยพลการที่จะทำให้เกิดระบบฐานข้อมูลในการดำเนินการมันจึงSQL ฉีด
ผลลัพธ์?
โรงเรียน=> เลือก* จากนักเรียน;
ข้อผิดพลาด: ความสัมพันธ์"นักเรียน" ไม่ได้อยู่
บรรทัดที่1 : เลือก* จากนักเรียน; ^
การฉีด SQL เป็นฐานข้อมูลที่เทียบเท่ากับช่องโหว่การเรียกใช้โค้ดจากระยะไกลในระบบปฏิบัติการหรือแอพพลิเคชัน ผลกระทบที่อาจเกิดขึ้นจากการโจมตีการฉีด SQL ที่ประสบความสำเร็จไม่สามารถประเมินได้ต่ำกว่า - ขึ้นอยู่กับระบบฐานข้อมูลและการกำหนดค่าแอปพลิเคชันผู้โจมตีสามารถใช้เพื่อทำให้ข้อมูลสูญหาย (เช่นในกรณีนี้) เข้าใช้ข้อมูลโดยไม่ได้รับอนุญาต รหัสโดยพลการในเครื่องโฮสต์เอง
ตามที่ระบุไว้ในหนังสือการ์ตูน XKCD วิธีหนึ่งในการป้องกันการโจมตี SQL injection คือการฆ่าเชื้ออินพุตของฐานข้อมูลเช่นโดยการหลีกเลี่ยงอักขระพิเศษเพื่อที่พวกเขาจะไม่สามารถแก้ไขคำสั่ง SQL พื้นฐานและดังนั้นจึงไม่สามารถทำให้เกิดการเรียกใช้งาน หากคุณใช้การสืบค้นแบบกำหนดพารามิเตอร์เช่นโดยใช้SqlParameter
ใน ADO.NET อย่างน้อยที่สุดการป้อนข้อมูลจะถูกทำให้สะอาดโดยอัตโนมัติเพื่อป้องกันการฉีด SQL
อย่างไรก็ตามการฆ่าเชื้ออินพุตที่ระดับแอปพลิเคชันอาจไม่หยุดเทคนิคการฉีด SQL ขั้นสูง ตัวอย่างเช่นมีวิธีที่จะหลีกเลี่ยงmysql_real_escape_string
ฟังก์ชัน PHP สำหรับการป้องกันเพิ่มเติมระบบฐานข้อมูลจำนวนมากสนับสนุนงบเตรียม หากนำไปใช้อย่างเหมาะสมในส่วนแบ็คเอนด์คำสั่งที่เตรียมไว้จะทำให้ SQL injection เป็นไปไม่ได้โดยการจัดการกับอินพุตข้อมูลโดยแยกความหมายจากส่วนที่เหลือของคำสั่ง