SQL injections ช่องโหว่เมื่อใช้โมเดล SQL ของ Zend Framework


15

เมื่อเข้าร่วมตารางฉันใช้โมเดล SQL ของ Zend Framework เช่นฉันปรับเปลี่ยนรหัสจริงของฉัน แต่ฉันคิดว่าคุณจะได้รับคะแนน:

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

หน้าถูกโหลดด้วยพารามิเตอร์ ajax และ $ section จะถูกส่งเป็นพารามิเตอร์ GET ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com)

นี่คือปัญหาถ้าใครบางคนทำสิ่งนี้:

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

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

คำถาม:

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

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


1
คุณสามารถใช้: $db = Mage::getSingleton('core/resource')->getConnection('core_read');และแม้ในกรณีของคุณดูที่$db->quote() $db->quoteIntoหาก$thisเป็นทรัพยากรที่คุณสามารถทำ: ถ้าหากมันเป็นคอลเลกชันที่คุณสามารถทำ:$this->getConnection('core_read')->quoteInto() $this->getResource()->getConnection('core_read')->quoteInto()ตามเส้นเหล่านั้น ถ้านั่นจะช่วยนำทางคุณไปสู่เป้าหมายของคุณ
เถ้า

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

เกิดอะไรขึ้นถ้าคุณเริ่มต้นด้วยการปิด'? งั้น' AND (SELECT ...) 'เหรอ? อย่างไรก็ตามฉันไม่คิดว่า Zend จะไม่พูดเรื่องนี้ ... และถ้าคุณใช้การเชื่อมโยง PDO จะจัดการสิ่งนี้ ไม่เคยใช้การต่อข้อมูลแบบต่อยเช่นนี้:"sections.section= '$section'"
7ochem

@ 7ochem ในกรณีเช่นนี้คุณต้องผูกพารามิเตอร์โดยใช้? และ 'จะกลายเป็น \' แต่ถ้าคุณใช้ค่าจำนวนเต็มคุณไม่ต้องผูกมันเพราะคุณสามารถทำความสะอาดได้โดยใช้ฟังก์ชั่น php intval () และ 'บางสิ่งจะกลายเป็น 0
JohnyFree

คำตอบ:


8

ตรวจสอบข้อมูลที่คุณป้อน!

ดีและมากที่สุดเท่าที่จะทำได้

คำแนะนำสำหรับการตรวจสอบของคุณ:

  1. ตรวจสอบความยาวของตัวแปรที่คุณได้รับผ่าน GET-parameter ไม่จำเป็นต้องยอมรับสตริงที่ยาวไม่สิ้นสุด

  2. ตรวจสอบความถูกต้องสำหรับชื่อโดเมน รูปแบบชื่อโดเมนที่คุณคาดหวังมีรูปแบบใด เป็น www.mydomain.tld เสมอหรือไม่ สร้าง regex ที่ตรวจสอบการจับคู่หรือ (ดีกว่า) ใช้Zend_Validate_Hostname:

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. รายการที่อนุญาต: คุณรู้จักชื่อโดเมนที่คาดหวังหรือไม่ คุณสามารถสร้างรายการของโดเมนที่อนุญาตและตรวจสอบกับพวกเขา วางส่วนที่เหลือ

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. การขึ้นบัญชีดำและชื่อโดเมนหรือตัวละคร: หากคุณคาดว่าจะเป็นชื่อโดเมนคุณไม่จำเป็นต้องยอมรับอักขระอื่นนอกจาก az และ 0-9 และ " (ยกเว้นว่าคุณกำลังทำงานกับชื่อโดเมนพิเศษ)

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