ฉันต้องป้องกันการแทรก SQL หรือไม่ถ้าฉันใช้ดรอปดาวน์?


97

ฉันเข้าใจว่าคุณไม่ควรเชื่อถือการป้อนข้อมูลของผู้ใช้จากแบบฟอร์มเนื่องจากมีโอกาสเกิดการแทรก SQL

อย่างไรก็ตามสิ่งนี้ใช้กับแบบฟอร์มที่อินพุตเพียงรายการเดียวมาจากดรอปดาวน์ (ดูด้านล่าง) หรือไม่

ฉันกำลังบันทึก$_POST['size']ลงในเซสชันซึ่งจะใช้ทั่วทั้งไซต์เพื่อสืบค้นฐานข้อมูลต่างๆ (ด้วยmysqliSelect query) และการฉีด SQL ใด ๆ จะเป็นอันตรายอย่างแน่นอน (อาจลดลง)

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

<form action="welcome.php" method="post">
<select name="size">
  <option value="All">Select Size</option> 
  <option value="Large">Large</option>
  <option value="Medium">Medium</option>
  <option value="Small">Small</option>
</select>
<input type="submit">
</form>

112
ใช่. ไม่มีอะไรที่จะป้องกันไม่ให้ผู้บุกรุกจากการส่งสิ่งที่พวกเขาต้องการค่าของคุณใน<select>การป้อนข้อมูล แม้แต่ผู้ใช้ทางเทคนิคเล็กน้อยก็สามารถเพิ่มตัวเลือกเพิ่มเติมได้โดยใช้คอนโซลเบราว์เซอร์ หากคุณเก็บรายการที่อนุญาตพิเศษของอาร์เรย์ของค่าที่มีอยู่และเปรียบเทียบอินพุตกับมันคุณสามารถลดค่านั้นได้ (และคุณควรจะป้องกันค่าที่ไม่ต้องการ)
Michael Berkowski

13
คุณควรเข้าใจสิ่งที่ร้องขอ / การตอบกลับพื้นฐานและสิ่งที่ไม่สำคัญว่าส่วนหน้าจะสร้างขึ้นจากคำขอเช่นใดในกรณีนี้แบบเลื่อนลง
Royal Bg

13
@YourCommonSense เพราะเป็นคำถามที่ดี ไม่ใช่ทุกคนที่รู้ว่าลูกค้าเป็นอย่างไร สิ่งนี้จะกระตุ้นให้เกิดคำตอบที่มีค่ามากสำหรับไซต์นี้
Cruncher

8
@Cruncher ฉันเห็น สำหรับ stackoverflowian โดยเฉลี่ยมันเป็นวิทยาศาสตร์จรวดที่พวกเขาใหม่กว่าเคยได้ยินมาก่อน แม้จะมีคำถามที่โหวตมากที่สุดภายใต้แท็ก PHP
สามัญสำนึกของคุณ

9
"ฉันเข้าใจว่าคุณไม่ควรเชื่อถือข้อมูลที่ผู้ใช้ป้อน" ไม่มีข้อยกเว้น.
Prinzhorn

คำตอบ:


69

คุณสามารถทำสิ่งง่ายๆดังตัวอย่างต่อไปนี้เพื่อให้แน่ใจว่าขนาดที่โพสต์เป็นไปตามที่คุณคาดหวัง

$possibleOptions = array('All', 'Large', 'Medium', 'Small');

if(in_array($_POST['size'], $possibleOptions)) {
    // Expected
} else {
    // Not Expected
}

จากนั้นใช้ mysqli_ * หากคุณใช้ php> = 5.3.0 เวอร์ชันที่คุณควรจะเป็นเพื่อบันทึกผลลัพธ์ของคุณ หากใช้อย่างถูกต้องสิ่งนี้จะช่วยในการฉีด sql


นี่คือ OliverBS 'รายการที่อนุญาตพิเศษ' ในเวอร์ชันชวเลขหรือไม่
Tatters

ไม่ใช่แค่เวอร์ชันพื้นฐานจริงๆคุณสามารถเพิ่มค่าลงในฐานข้อมูลเพื่อตรวจสอบเพื่อให้ง่ายขึ้นและนำกลับมาใช้ใหม่ได้หรืออาจสร้างคลาสที่อนุญาตพิเศษด้วยวิธีการเฉพาะสำหรับรายการที่อนุญาตแต่ละรายการเพื่อตรวจสอบ หากคุณไม่ต้องการใช้ฐานข้อมูลคุณสมบัติรายการที่อนุญาตอาจอยู่ภายในคุณสมบัติอาร์เรย์ในคลาสรายการที่อนุญาตของคุณ
Oliver Bayes-Shelton

9
อย่างไรก็ตามคุณต้องใช้งบเตรียม (แนะนำ) mysqli_real_escape_stringหรือ หลีกเลี่ยงค่าอย่างถูกต้องเมื่อส่งออก (เช่นใช้htmlspecialchars ()ในเอกสาร HTML)
ComFreek

4
ฉันขอแนะนำให้ตั้งค่าพารามิเตอร์ที่สามin_arrayเป็นtrueเพื่อการเปรียบเทียบอย่างเข้มงวด ฉันไม่แน่ใจว่ามีอะไรผิดพลาดบ้าง แต่การเปรียบเทียบแบบหลวม ๆ นั้นค่อนข้างแปลก
Brilliand

1
ค่า @OliverBS $ _POST สามารถเป็นอาร์เรย์ได้ สตริงตัวเลขเปรียบเทียบเป็นตัวเลข ('5' == '05') ฉันไม่คิดว่าคุณมีช่องโหว่ด้านความปลอดภัยในตัวอย่างเฉพาะของคุณ แต่กฎนั้นซับซ้อนและอาจเปิดช่องโหว่ด้วยเหตุผลที่ฉันไม่เข้าใจ การเปรียบเทียบอย่างเข้มงวดนั้นง่ายกว่าที่จะให้เหตุผลและใช้งานได้อย่างปลอดภัย
Brilliand

195

ใช่คุณต้องป้องกันสิ่งนี้

ให้ฉันแสดงให้คุณเห็นว่าทำไมโดยใช้คอนโซลนักพัฒนาของ Firefox:

ฉันได้แก้ไขค่าใดค่าหนึ่งในเมนูดร็อปดาวน์ให้เป็นคำสั่งดร็อปตาราง

หากคุณไม่ล้างข้อมูลนี้ฐานข้อมูลของคุณจะถูกทำลาย (นี่อาจไม่ใช่คำสั่ง SQL ที่ถูกต้องทั้งหมด แต่ฉันหวังว่าฉันจะเข้าใจประเด็นนี้)

เพียงเพราะคุณ จำกัด ตัวเลือกที่มีอยู่ในดรอปดาวน์ของคุณไม่ได้หมายความว่าคุณ จำกัด ข้อมูลที่ฉันสามารถส่งเซิร์ฟเวอร์ของคุณได้

หากคุณพยายาม จำกัด สิ่งนี้เพิ่มเติมโดยใช้พฤติกรรมบนเพจของคุณตัวเลือกของฉันรวมถึงการปิดใช้งานพฤติกรรมนั้นหรือเพียงแค่เขียนคำขอ HTTP ที่กำหนดเองไปยังเซิร์ฟเวอร์ของคุณซึ่งเลียนแบบการส่งแบบฟอร์มนี้ มีเครื่องมือที่เรียกว่าcurl ที่ใช้สำหรับสิ่งนั้นและฉันคิดว่าคำสั่งในการส่งการฉีด SQL นี้จะมีลักษณะดังนี้:

curl --data "size=%27%29%3B%20DROP%20TABLE%20*%3B%20--"  http://www.example.com/profile/save

(นี่อาจไม่ใช่คำสั่ง curl ที่ถูกต้อง แต่อีกครั้งฉันหวังว่าฉันจะเข้าใจจุดนี้)

ดังนั้นฉันจะย้ำอีกครั้ง:

ไม่เคยเชื่อถือข้อมูลของผู้ใช้ ปกป้องตัวเองอยู่เสมอ

อย่าถือว่าการป้อนข้อมูลของผู้ใช้จะปลอดภัย อาจไม่ปลอดภัยแม้ว่าจะมาถึงด้วยวิธีการอื่นที่ไม่ใช่แบบฟอร์มก็ตาม ไม่มีสิ่งใดที่น่าเชื่อถือพอที่จะละทิ้งการป้องกันตัวเองจากการฉีด SQL


24
curlไม่ต้องพูดถึงงานหัตถกรรมบรรจุที่กำหนดเองด้วย ทำความสะอาดอินพุตฝั่งเซิร์ฟเวอร์เสมอ !
recursion.ninja

14
ภาพพูดได้มากกว่าหนึ่งพันคำ
davidkonrad

4
นี่ควรเป็นคำตอบเริ่มต้น curlนอกจากนี้ยังควรจะรวมถึงบางสิ่งบางอย่างเกี่ยวกับ ผู้คนไม่เข้าใจว่าคุณสามารถส่งคำขอ HTTP จากที่ใดก็ได้โดยใช้รูปแบบใดก็ได้และส่งผ่านค่าใดก็ได้ขึ้นอยู่กับเซิร์ฟเวอร์เพื่อให้แน่ใจว่าคำขอนั้นถูกต้องก่อนที่จะประมวลผล
retrohacker

2
น่ารัก! มันคือโต๊ะบ๊อบบี้ตัวน้อย!
ออร่า

45

เนื่องจากคำถามนี้ถูกแท็กด้วย นี่คือคำตอบเกี่ยวกับการโจมตีประเภทนี้:

ในขณะที่คุณได้รับการบอกในความคิดเห็นที่คุณต้องใช้งบเตรียมสำหรับทุกคำเดียวที่เกี่ยวข้องกับข้อมูลตัวแปรใด ๆ กับไม่มีข้อยกเว้น

ไม่ว่าจะเป็น HTML อะไรก็ตาม!
จำเป็นอย่างยิ่งที่จะต้องเข้าใจว่าคิวรี SQL ต้องได้รับการจัดรูปแบบอย่างถูกต้องโดยไม่คำนึงถึงปัจจัยภายนอกใด ๆไม่ว่าจะเป็นอินพุต HTML หรืออย่างอื่นก็ตาม

แม้ว่าคุณจะสามารถใช้ white-list ที่แนะนำในคำตอบอื่น ๆ เพื่อวัตถุประสงค์ในการตรวจสอบอินพุตได้ แต่ก็ไม่ควรส่งผลต่อการดำเนินการใด ๆ ที่เกี่ยวข้องกับ SQL - ต้องยังคงเหมือนเดิมไม่ว่าคุณจะตรวจสอบอินพุต HTML หรือไม่ก็ตาม หมายความว่าคุณยังต้องใช้คำสั่งที่เตรียมไว้เมื่อเพิ่มตัวแปรใด ๆ ลงในแบบสอบถาม

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

นอกจากนี้คำถามนี้ยังถูกแท็กด้วย . โดยส่วนใหญ่เป็นอุบัติเหตุผมเข้าใจ แต่อย่างไรก็ตามผมต้องเตือนคุณว่า mysqli ดิบไม่ได้เป็นทดแทนที่เพียงพอสำหรับ mysq_ เก่าฟังก์ชั่น เพียงเพราะหากใช้ในรูปแบบเก่าจะเพิ่มความปลอดภัยไม่ได้เลย แม้ว่าการรองรับงบที่เตรียมไว้นั้นจะเจ็บปวดและยุ่งยาก แต่จนถึงจุดที่ผู้ใช้ PHP โดยเฉลี่ยไม่สามารถใช้ความพยายามได้เลย ดังนั้นหากไม่มี ORM หรือไลบรารีนามธรรมบางประเภทเป็นตัวเลือกPDOจึงเป็นทางเลือกเดียวของคุณ


5
ผม = สุ่ม (0, 15); // แบบสอบถามโดยใช้ i. ฉันยังต้องเตรียมแถลงการณ์ที่นี่หรือไม่?
Cruncher

2
การใช้งานrandomคืออะไร?
Slicedpan

9
@YourCommonSense มองแคบ? สำหรับฉัน "ทำ X เสมอและฉันจะไม่ให้เหตุผลสำหรับสิ่งนี้" นั้นมองอย่างแคบ
Cruncher

5
@Cruncher ฉันไม่สามารถคิดเหตุผลใดที่จะไม่เสมอใช้งบเตรียมทุกเวลาสำหรับทุกอย่างเสมอ คุณช่วยบอกฉันได้ไหม
Wesley Murch

3
@Cruncher ที่ฉันเห็นด้วยดูเหมือนว่าคุณกำลังเล่น Devil's Advocate ข้อตกลงในคำตอบคือยัง"ที่เกี่ยวข้องกับข้อมูลตัวแปรใด ๆ" มีบางกรณีเช่น PHP int casting แต่ดูเหมือนว่าจะดีกว่าถ้าใช้งบที่เตรียมไว้ การบอกคน (ที่ไม่มีประสบการณ์) ว่า "การเพิ่มประสิทธิภาพ" เล็กน้อยนั้นสำคัญกว่าการรักษาความปลอดภัย คำตอบคือ "ไม่สมบูรณ์" แต่จะส่งข้อความที่หนักแน่นว่าคนอื่นเพิกเฉย ฉันจะพักคดีของฉัน
Wesley Murch

12

ใช่.

ทุกคนสามารถปลอมแปลงอะไรก็ได้สำหรับค่าที่ส่งจริง -

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

if(in_array($_POST['ddMenu'], $dropDownValues){

    $valueYouUseLaterInPDO = $dropDownValues[array_search("two", $arr)];

} else {

    die("effin h4x0rs! Keep off my LAMP!!"); 

}

5
คำตอบนี้ไม่สมบูรณ์นอกจากนี้คุณควรใช้คำสั่งที่เตรียมไว้เพื่อให้การฉีดเป็นไปไม่ได้ไม่ว่าจะตั้งค่าเป็น
เท่าใดก็ตาม

7
@Slicedpan จริงเหรอ? ฟังดูเหมือนคุณกำลังกระโดดขึ้นไปบนแบนด์แวกอนโดยไม่รู้ว่าทำไม ... ถ้าฉันมีข้อมูลที่เป็นไปได้จำนวนหนึ่งในแบบสอบถามฉันจะสามารถยืนยันได้ว่าทุกอย่างโอเค (ซึ่งฉันรู้เพราะฉันสร้างมันขึ้นมา) จากนั้นคุณจะไม่มีประโยชน์ด้านความปลอดภัยเพิ่มเติมจากการใช้คำสั่งที่เตรียมไว้
Cruncher

3
ยกเว้นว่าการบังคับใช้คำสั่งที่เตรียมไว้เป็นแบบแผนจะช่วยป้องกันคุณจากการนำช่องโหว่การแทรก SQL มาใช้ในอนาคต
Slicedpan

1
@Cruncher การทำสัญญา "ค่าทั้งหมดในเมนูแบบเลื่อนลงจะปลอดภัยเสมอ" เป็นสัญญาที่ไม่ปลอดภัยอย่างยิ่งที่จะทำ ค่ามีการเปลี่ยนแปลงโค้ดไม่จำเป็นต้องอัปเดต คนที่อัปเดตค่าอาจไม่รู้ด้วยซ้ำว่าค่าอะไรไม่ปลอดภัย! โดยเฉพาะอย่างยิ่งในขอบเขตของการเขียนโปรแกรมบนเว็บซึ่งเต็มไปด้วยปัญหาด้านความปลอดภัยทุกประเภทการอ่านเรื่องแบบนี้เป็นเพียงการขาดความรับผิดชอบ (และคำพูดที่ไม่ค่อยดีอื่น ๆ )
hyde

1
@Cruncher หากคุณจัดการกับข้อมูล SQL ของคุณอย่างถูกต้องคุณสามารถยอมรับอินพุตใด ๆโดยไม่รบกวนการทำงานของ SQL ควรเตรียมส่วนของ SQL ให้พร้อมและพร้อมที่จะรับทุกสิ่งไม่ว่าจะมาจากไหน อย่างอื่นมีโอกาสเกิดข้อผิดพลาดได้ง่าย
glglgl

8

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

<?php
// No, you don't need to specify the numbers in the array but as we're using them I always find having them visually there helpful.
$sizes = array(0 => 'All', 1 => 'Large', 2 => 'Medium', 3 => 'Small');
$size = filter_input(INPUT_POST, "size", FILTER_VALIDATE_INT);

echo '<select name="size">';
foreach($sizes as $i => $s) {
    echo '<option value="' . $i . '"' . ($i == $size ? ' selected' : '') . '>' . $s . '</option>';
}
echo '</select>';

จากนั้นคุณสามารถใช้$sizeในแบบสอบถามของคุณด้วยความรู้ว่าจะมีเพียงFALSEจำนวนเต็มหรือจำนวนเต็ม


2
@OliverBS คืออะไรfilter_inputถ้าไม่ใช่การตรวจสอบทางฝั่งเซิร์ฟเวอร์? ไม่มีใครสามารถโพสต์อะไรได้เลยนอกจากจำนวนเต็ม
Styphon

ขอบคุณ Styphon ดังนั้นสิ่งนี้จะแทนที่แบบฟอร์มใน OP? และสิ่งนี้จะใช้ได้กับฟอร์มขนาดใหญ่ที่มีเมนูแบบเลื่อนลงหลายรายการหรือไม่ หากฉันเพิ่มรายการแบบเลื่อนลงอีกรายการเพื่อพูดว่า 'สี'?
Tatters

@SamuelTattersfield ใช่และใช่ คุณสามารถใช้สิ่งนี้สำหรับรายการแบบเลื่อนลงได้มากเท่าที่คุณต้องการโดยมีตัวเลือกมากเท่าที่คุณต้องการ คุณเพียงแค่สร้างอาร์เรย์ใหม่สำหรับรายการแบบเลื่อนลงแต่ละรายการและใส่ตัวเลือกทั้งหมดสำหรับรายการแบบเลื่อนลงในอาร์เรย์
Styphon

ดี! ฉันชอบมัน. ฉันจะลองดูว่าฉันได้อะไรจากการทดสอบ
Tatters

@SamuelTattersfield เยี่ยมมากอย่าลืมใช้filter_inputส่วนนี้ด้วยเพื่อการตรวจสอบความถูกต้องมิฉะนั้นจะมีประโยชน์เหมือนกับกาน้ำชาช็อคโกแลตเพื่อความปลอดภัย
Styphon

7

คำตอบอื่น ๆ ครอบคลุมสิ่งที่คุณต้องรู้อยู่แล้ว แต่อาจจะช่วยชี้แจงเพิ่มเติมได้บ้าง:

มีสองสิ่งที่คุณต้องทำ:

1. ตรวจสอบข้อมูลแบบฟอร์ม

ดังที่คำตอบของ Jonathan Hobbsแสดงให้เห็นอย่างชัดเจนการเลือกองค์ประกอบ html สำหรับการป้อนข้อมูลแบบฟอร์มไม่ได้ทำการกรองที่เชื่อถือได้สำหรับคุณ

โดยปกติการตรวจสอบความถูกต้องจะทำในลักษณะที่ไม่เปลี่ยนแปลงข้อมูล แต่จะแสดงแบบฟอร์มอีกครั้งโดยมีการระบุฟิลด์ว่า "โปรดแก้ไขสิ่งนี้"

เฟรมเวิร์กและ CMS ส่วนใหญ่มีตัวสร้างฟอร์มที่ช่วยคุณในงานนี้ และไม่ใช่แค่นั้นพวกเขายังช่วยต่อต้าน CSRF (หรือ "XSRF") ซึ่งเป็นการโจมตีอีกรูปแบบหนึ่ง

2. Sanitize / Escape ตัวแปรในคำสั่ง SQL ..

.. หรือปล่อยให้งบที่เตรียมไว้ทำงานแทนคุณ.

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

โดยทั่วไปตัวแปรใด ๆ ที่คุณแทรกลงในคำสั่ง MySQL ควรเป็นสตริงหรือสิ่งที่ PHP สามารถเปลี่ยนเป็นสตริงที่ MySQL สามารถแยกย่อยได้อย่างน่าเชื่อถือ เช่นตัวเลข

สำหรับสตริงคุณต้องเลือกหนึ่งในหลายวิธีเพื่อหลีกเลี่ยงสตริงซึ่งหมายความว่าแทนที่อักขระใด ๆ ที่อาจมีผลข้างเคียงใน MySQL

  • ใน MySQL + PHP แบบเก่า mysql_real_escape_string () จะทำงาน ปัญหาคือมันง่ายเกินไปที่จะลืมดังนั้นคุณควรใช้คำสั่งที่เตรียมไว้หรือเครื่องมือสร้างแบบสอบถาม
  • ใน MySQLi คุณสามารถใช้คำสั่งที่เตรียมไว้
  • เฟรมเวิร์กและ CMS ส่วนใหญ่มีตัวสร้างคิวรีที่ช่วยคุณในงานนี้

หากคุณกำลังจัดการกับตัวเลขคุณสามารถละเว้นการหลีกเลี่ยงและเครื่องหมายคำพูด (นี่คือสาเหตุที่ข้อความที่เตรียมไว้อนุญาตให้ระบุประเภท)

สิ่งสำคัญคือต้องชี้ให้เห็นว่าคุณหลีกเลี่ยงตัวแปรสำหรับคำสั่ง SQL และไม่ใช่สำหรับฐานข้อมูลเองและไม่ได้สำหรับฐานข้อมูลของตัวเอง ฐานข้อมูลจะจัดเก็บสตริงดั้งเดิม แต่คำสั่งต้องการเวอร์ชันที่ใช้ Escape

จะเกิดอะไรขึ้นถ้าคุณละเว้นสิ่งใดสิ่งหนึ่งเหล่านี้

หากคุณไม่ได้ใช้การตรวจสอบความถูกต้องของฟอร์มแต่คุณทำความสะอาดอินพุต SQL ของคุณคุณอาจเห็นสิ่งเลวร้ายทุกประเภทเกิดขึ้น แต่คุณจะไม่เห็นการแทรก SQL (*)

ขั้นแรกอาจทำให้ใบสมัครของคุณอยู่ในสถานะที่คุณไม่ได้วางแผนไว้ เช่นหากคุณต้องการคำนวณอายุเฉลี่ยของผู้ใช้ทั้งหมด แต่ผู้ใช้รายหนึ่งระบุอายุเป็น "aljkdfaqer" การคำนวณของคุณจะล้มเหลว

ประการที่สองอาจมีการโจมตีด้วยการฉีดอื่น ๆ ทุกประเภทที่คุณต้องพิจารณาเช่นอินพุตของผู้ใช้อาจมีจาวาสคริปต์หรือสิ่งอื่น ๆ

ยังคงมีปัญหากับฐานข้อมูลเช่นถ้าเขตข้อมูล (คอลัมน์ตารางฐานข้อมูล) จำกัด ไว้ที่ 255 อักขระและสตริงยาวกว่านั้น หรือถ้าฟิลด์ยอมรับเฉพาะตัวเลขและคุณพยายามบันทึกสตริงที่ไม่ใช่ตัวเลขแทน แต่นี่ไม่ใช่ "การฉีด" แต่เป็นเพียง "การขัดข้องของแอปพลิเคชัน"

แต่แม้ว่าคุณจะมีฟิลด์ข้อความว่างที่คุณอนุญาตให้ป้อนข้อมูลใด ๆ โดยไม่มีการตรวจสอบความถูกต้องเลยคุณยังคงสามารถบันทึกข้อมูลนี้ลงในฐานข้อมูลได้เช่นเดียวกับที่คุณต้องหลีกเลี่ยงอย่างถูกต้องเมื่อไปที่คำสั่งฐานข้อมูล ปัญหาเกิดขึ้นเมื่อคุณต้องการใช้สตริงนี้ที่ใดที่หนึ่ง

(*) หรือนี่จะเป็นอะไรที่แปลกใหม่จริงๆ

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

ขั้นแรกคุณต้องเสี่ยงว่าเมื่อคุณบันทึกข้อมูลลงในฐานข้อมูลและโหลดอีกครั้งข้อมูลนั้นจะไม่เป็นข้อมูลเดิมอีกต่อไป "สูญหายในการแปล"

ประการที่สองอาจส่งผลให้คำสั่ง SQL ไม่ถูกต้องและทำให้แอปพลิเคชันของคุณขัดข้อง เช่นหากตัวแปรใด ๆ มีเครื่องหมายอัญประกาศหรือเครื่องหมายอัญประกาศคู่ขึ้นอยู่กับประเภทของใบเสนอราคาที่คุณใช้คุณจะได้รับคำสั่ง MySQL ที่ไม่ถูกต้อง

ประการที่สามยังสามารถทำให้เกิดการฉีด SQL

หากข้อมูลที่ผู้ใช้ของคุณป้อนจากแบบฟอร์มได้รับการกรอง / ตรวจสอบความถูกต้องแล้วการฉีด SQl โดยเจตนาอาจมีโอกาสน้อยลงหากข้อมูลของคุณลดลงเป็นรายการตัวเลือกแบบฮาร์ดโค้ดหรือหากถูก จำกัด ไว้ที่ตัวเลข แต่สามารถใช้การป้อนข้อความฟรีสำหรับการแทรก SQL ได้หากคุณไม่ได้หลีกเลี่ยงตัวแปรในคำสั่ง SQL อย่างถูกต้อง

และแม้ว่าคุณจะไม่มีการป้อนแบบฟอร์มเลยคุณก็ยังสามารถมีสตริงจากแหล่งข้อมูลทุกประเภท: อ่านจากระบบไฟล์, คัดลอกจากอินเทอร์เน็ตเป็นต้นไม่มีใครสามารถรับประกันได้ว่าสตริงเหล่านี้ปลอดภัย


ข้อมูลที่ยาวเกินไปไม่ใช่สตริงในฟิลด์ตัวเลขจะผิดพลาด
สามัญสำนึกของคุณ

อืมเพิ่งลองตอนนี้และแสดงคำเตือนแทนข้อผิดพลาด ฉันคิดว่ามันเป็น PDO ที่ทำให้สิ่งนี้กลายเป็นข้อผิดพลาด ฉันแน่ใจว่าฉันได้พูดคุยในหลาย ๆ ประเด็นใน drupal.org ซึ่งบางสตริงยาวเกินไปสำหรับ varchar
donquixote

6

เว็บเบราว์เซอร์ของคุณไม่ "รู้" ว่ากำลังรับเพจจาก php แต่สิ่งที่เห็นคือ html และเลเยอร์ http รู้น้อยกว่านั้นด้วยซ้ำ คุณต้องสามารถจัดการอินพุตได้เกือบทุกประเภทที่สามารถข้ามเลเยอร์ http ได้ (โชคดีสำหรับ php อินพุตส่วนใหญ่จะให้ข้อผิดพลาดอยู่แล้ว) หากคุณกำลังพยายามป้องกันไม่ให้คำขอที่เป็นอันตรายไปยุ่งกับฐานข้อมูลของคุณคุณต้องสมมติว่าอีกฝ่ายรู้ว่าเขากำลังทำอะไรและเขาไม่ได้ จำกัด เฉพาะสิ่งที่คุณเห็นในเบราว์เซอร์ของคุณภายใต้สถานการณ์ปกติ ( ไม่ต้องพูดถึงสิ่งที่คุณสามารถเล่นได้ด้วยเครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์) ใช่คุณต้องรองรับอินพุตใด ๆ จากดรอปดาวน์ของคุณ แต่สำหรับอินพุตส่วนใหญ่คุณสามารถให้ข้อผิดพลาดได้


6

ข้อเท็จจริงที่ว่าคุณ จำกัด ผู้ใช้ให้ใช้เฉพาะค่าจากรายการแบบเลื่อนลงบางรายการนั้นไม่เกี่ยวข้อง ผู้ใช้ทางเทคนิคสามารถจับคำขอ http ที่ส่งไปยังเซิร์ฟเวอร์ของคุณก่อนที่จะออกจากเครือข่ายของตนแก้ไขโดยใช้เครื่องมือเช่นพร็อกซีเซิร์ฟเวอร์ในเครื่องจากนั้นดำเนินการต่อตามวิธีการนั้น เมื่อใช้คำขอที่เปลี่ยนแปลงพวกเขาสามารถส่งค่าพารามิเตอร์ที่ไม่ใช่ค่าที่คุณระบุไว้ในรายการแบบเลื่อนลง นักพัฒนาต้องมีความคิดว่าข้อ จำกัด ของไคลเอ็นต์มักไม่มีความหมายเนื่องจากสิ่งใด ๆ ในไคลเอนต์สามารถเปลี่ยนแปลงได้ จำเป็นต้องมีการตรวจสอบความถูกต้องของเซิร์ฟเวอร์ในทุกๆจุดที่ข้อมูลไคลเอนต์เข้ามา ผู้โจมตีอาศัยความไร้เดียงสาของนักพัฒนาในแง่มุมนี้ แต่เพียงผู้เดียว


5

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

SELECT * FROM table WHERE size = ?

เมื่อคุณใส่ข้อความค้นหาเช่นข้างต้นพร้อมข้อความที่ไม่ได้รับการตรวจสอบความสมบูรณ์ (อินพุตไม่ได้รับการตรวจสอบความถูกต้องบนเซิร์ฟเวอร์) และมีการแทรกโค้ด SQL ระบบจะจัดการอย่างถูกต้อง กล่าวอีกนัยหนึ่งคำขอจะส่งผลให้สิ่งนี้เกิดขึ้นในชั้นฐานข้อมูล:

SELECT * FROM table WHERE size = 'DROP table;'

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


4

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

ตัวอย่างสิ่งที่สามารถและจะเกิดขึ้นเมื่อคุณไว้วางใจลูกค้า


4

แฮ็กเกอร์สามารถข้ามเบราว์เซอร์ได้อย่างสมบูรณ์รวมถึงการตรวจสอบฟอร์ม Javascript ด้วยการส่งคำขอโดยใช้ Telnet แน่นอนเขาจะดูโค้ดของหน้า html ของคุณเพื่อรับชื่อฟิลด์ที่เขาต้องใช้ แต่จากนั้นมันก็เป็น 'ทุกอย่าง' สำหรับเขา ดังนั้นคุณต้องตรวจสอบค่าทั้งหมดที่ส่งบนเซิร์ฟเวอร์ราวกับว่าค่าเหล่านั้นไม่ได้มาจากหน้า html ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.