Kerentanan injeksi SQL saat menggunakan model SQL dari Zend Framework

15

Saat bergabung dengan tabel, saya menggunakan model SQL dari Zend Framework. Sebagai contoh saya memodifikasi kode saya yang sebenarnya, tetapi saya pikir Anda akan mengerti maksudnya:

$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'); 

Halaman dimuat dengan ajax dan parameter $ section dikirim sebagai parameter GET ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com).

Sekarang inilah masalahnya jika seseorang melakukan sesuatu seperti ini:

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)

Dengan cara ini pengguna dapat membuang seluruh basis data. Data tidak akan ditampilkan, tetapi tetap SQL akan melakukan dump yang dapat menyebabkan kelebihan sql.

Pertanyaan:

  1. Apa cara terbaik untuk mencegah skenario seperti itu?
  2. Sekarang saya khawatir dengan pelanggan sebelumnya. Apakah dengan kode ini dimungkinkan untuk melakukan tindakan yang lebih berisiko, seperti menghapus atau mengubah tabel? Saya kira bukan karena Anda tidak dapat menempatkan pernyataan selain SELECT di dalam subselect sehingga DELETE akan menghasilkan kesalahan sintaksis sql. Apakah saya benar?

UPDATE: Contoh saya bukan ilustrasi yang tepat dari injeksi SQL karena ada 'tanda sekitar bagian $ dan dengan demikian tidak akan mungkin untuk membuat injeksi. Bagaimanapun ini akan mungkin terjadi ketika mengharapkan nilai integer dan ketika Anda tidak memfilter input integer. Lihat komentar saya di bawah.

JohnyFree
sumber
1
Anda dapat menggunakan: $db = Mage::getSingleton('core/resource')->getConnection('core_read');dan $db->quote()bahkan dalam kasus Anda lihat $db->quoteInto. Jika $thisadalah sumber daya, Anda bisa melakukan: $this->getConnection('core_read')->quoteInto()jika koleksi Anda bisa melakukan: $this->getResource()->getConnection('core_read')->quoteInto(). sepanjang garis itu. Jika itu membantu membimbing Anda menuju tujuan Anda.
ash
Saya baru menyadari bahwa skenario ini hanya mungkin jika nilai integer. Jika nilai varchar, maka akan selalu ada 'tanda sebelum (tanda dan dengan demikian (SELECTatau apa pun akan sama seperti string dan bukan berfungsi. Ketika bidang bilangan bulat, maka 'tidak diperlukan dan itu memungkinkan skenario seperti itu. Tapi integer harus selalu difilter intval()jadi ini juga bukan masalah.
JohnyFree
Bagaimana jika Anda mulai dengan menutup '? Jadi ' AND (SELECT ...) '? Ngomong-ngomong, saya tidak berpikir Zend tidak mengutip ini ... Dan jika Anda menggunakan binding, maka PDO akan menangani ini. Hanya tidak pernah menggunakan rangkaian sengatan seperti ini:"sections.section= '$section'"
7ochem
@ 7ochem dalam hal ini Anda HARUS mengikat parameter menggunakan? dan 'akan menjadi \'. Tetapi jika Anda menggunakan nilai integer, maka Anda tidak mengikatnya karena Anda dapat membersihkannya menggunakan fungsi intval () php dan 'sesuatu akan menjadi 0.
JohnyFree

Jawaban:

8

Validasi input Anda!

Sebagus dan sebanyak yang Anda bisa.

Beberapa saran untuk validasi Anda:

  1. Periksa panjang variabel yang Anda dapatkan melalui parameter GET. Tidak perlu menerima string panjang yang tidak pernah berakhir.

  2. Validasi untuk nama domain. Apa jenis format yang diharapkan dari nama domain Anda? Apakah selalu www.mydomain.tld? Buat regex yang memeriksa kecocokan atau penggunaan (lebih baik) Zend_Validate_Hostname:

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. Daftar Putih: Apakah Anda tahu nama domain mana yang diharapkan? Anda dapat membuat daftar domain yang diizinkan dan memeriksanya. Jatuhkan sisanya.

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. Blacklisting nama domain dan atau karakter: Jika Anda mengharapkan nama domain, tidak perlu menerima karakter lain selain az dan 0-9 dan "." (kecuali jika Anda bekerja dengan nama domain khusus).

Anna Völkl
sumber