Apa itu SQL Injection dan Bagaimana Mencegahnya dalam Aplikasi PHP?

Oleh itu, anda fikir pangkalan data SQL anda berprestasi dan selamat dari kemusnahan segera? Baiklah, SQL Injection tidak setuju!


Ya, ini adalah kehancuran sekejap yang sedang kita bicarakan, kerana saya tidak mahu membuka artikel ini dengan terminologi lumpuh biasa seperti “memperketat keselamatan” dan “mencegah akses jahat.” SQL Injection adalah satu helah lama dalam buku ini sehingga setiap orang, setiap pembangun, mengetahui tentangnya dengan sangat baik dan mengetahui cara mencegahnya. Kecuali untuk satu masa yang ganjil ketika mereka merosot, dan hasilnya tidak dapat disangka-sangka.

Sekiranya anda sudah mengetahui apa itu SQL Injection, jangan ragu untuk melangkau bahagian kedua artikel ini. Tetapi bagi mereka yang baru muncul dalam bidang pembangunan web dan bermimpi untuk mengambil peranan yang lebih senior, beberapa pengenalan adalah dalam rangka.

Apa itu SQL Injection?

Kunci untuk memahami SQL Injection adalah namanya: SQL + Injection. Kata “suntikan” di sini tidak mempunyai konotasi perubatan, melainkan penggunaan kata kerja “suntikan”. Bersama-sama, kedua-dua perkataan ini menyampaikan idea untuk memasukkan SQL ke dalam aplikasi web.

Menempatkan SQL ke dalam aplikasi web. . . hmmm. . . Bukankah itu yang sedang kita lakukan? Ya, tetapi kami tidak mahu penyerang memacu pangkalan data kami. Mari kita fahami bahawa dengan bantuan contoh.

Katakan anda membina laman web PHP khas untuk kedai e-dagang tempatan, jadi anda memutuskan untuk menambahkan borang hubungan seperti ini:

Nama awak

Mesej anda

Dan mari kita anggap fail send_message.php menyimpan semuanya dalam pangkalan data supaya pemilik kedai dapat membaca mesej pengguna di kemudian hari. Mungkin ada beberapa kod seperti ini:

<?php

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

// periksa sama ada pengguna ini sudah mempunyai mesej
mysqli_query ($ samb, "PILIH * dari mesej di mana nama = $ nama");

// Kod lain di sini

Oleh itu, anda mula-mula cuba melihat apakah pengguna ini sudah mempunyai mesej yang belum dibaca. Pertanyaan SELECT * dari mesej di mana name = $ name nampaknya cukup mudah, betul?

SALAH!

Dalam keadaan tidak bersalah, kami telah membuka pintu kepada pemusnahan pangkalan data kami dengan segera. Untuk ini berlaku, penyerang harus memenuhi syarat berikut:

  • Aplikasi ini berjalan di pangkalan data SQL (hari ini, hampir setiap aplikasi)
  • Sambungan pangkalan data semasa mempunyai kebenaran “edit” dan “hapus” pada pangkalan data
  • Nama-nama jadual penting dapat ditebak

Titik ketiga bermaksud bahawa sekarang bahawa penyerang tahu bahawa anda menjalankan kedai e-dagang, kemungkinan besar anda menyimpan data pesanan dalam tabel pesanan. Bersenjata dengan semua ini, yang perlu dilakukan penyerang adalah memberikan ini sebagai nama mereka:

Joe; pemotongan pesanan ;? Baik tuan! Mari kita lihat apa yang akan menjadi pertanyaan apabila ia dijalankan oleh skrip PHP:

PILIH * DARI mesej DI MANA nama = Joe; pesanan pemotongan;

Baiklah, bahagian pertama pertanyaan mempunyai ralat sintaks (tidak ada tanda petik di sekitar “Joe”), tetapi titik koma memaksa mesin MySQL untuk mula menafsirkan yang baru: perintah pemotongan. Sama seperti itu, dalam satu pertukaran tunggal, keseluruhan sejarah pesanan hilang!

Sekarang setelah anda mengetahui bagaimana SQL Injection berfungsi, inilah masanya untuk melihat cara menghentikannya. Dua syarat yang perlu dipenuhi untuk suntikan SQL yang berjaya adalah:

  1. Skrip PHP harus mempunyai hak mengubah / menghapus pada pangkalan data. Saya rasa ini berlaku untuk semua aplikasi dan anda tidak akan dapat menjadikan aplikasi anda hanya boleh dibaca. �� Dan tebak, walaupun kita membuang semua hak ubah suai, suntikan SQL masih boleh membolehkan seseorang menjalankan pertanyaan PILIH dan melihat semua pangkalan data, termasuk data sensitif. Dengan kata lain, mengurangkan tahap akses pangkalan data tidak berfungsi, dan aplikasi anda tetap memerlukannya.
  2. Input pengguna sedang diproses. Satu-satunya cara suntikan SQL dapat berfungsi adalah apabila anda menerima data dari pengguna. Sekali lagi, tidak praktikal untuk menghentikan semua input untuk aplikasi anda hanya kerana anda bimbang tentang suntikan SQL.

Mencegah suntikan SQL dalam PHP

Sekarang, memandangkan sambungan pangkalan data, pertanyaan, dan input pengguna adalah sebahagian dari kehidupan, bagaimana kita mencegah suntikan SQL? Syukurlah, ia cukup mudah, dan ada dua cara untuk melakukannya: 1) membersihkan input pengguna, dan 2) menggunakan penyataan yang disediakan.

Bersihkan input pengguna

Sekiranya anda menggunakan versi PHP yang lebih lama (5.5 atau lebih rendah, dan ini banyak berlaku pada hosting bersama), adalah bijak untuk menjalankan semua input pengguna anda melalui fungsi yang disebut mysql_real_escape_string (). Pada dasarnya, apa yang dilakukannya membuang semua watak khas dalam rentetan sehingga mereka kehilangan makna ketika digunakan oleh pangkalan data.

Sebagai contoh, jika anda mempunyai rentetan seperti saya string, karakter sebut harga tunggal (‘) dapat digunakan oleh penyerang untuk memanipulasi pertanyaan pangkalan data yang dibuat dan menyebabkan suntikan SQL. Menjalankannya melalui mysql_real_escape_string () menghasilkan tali, yang menambahkan garis miring terbalik pada satu petikan, melarikan diri. Akibatnya, keseluruhan rentetan sekarang diserahkan sebagai rentetan yang tidak berbahaya ke pangkalan data, dan bukannya dapat berpartisipasi dalam manipulasi pertanyaan.

Terdapat satu kelemahan dengan pendekatan ini: ini adalah teknik yang benar-benar lama yang sesuai dengan bentuk akses pangkalan data yang lebih lama di PHP. Sehingga PHP 7, fungsi ini bahkan tidak ada lagi, yang membawa kita ke penyelesaian seterusnya.

Gunakan penyataan yang disediakan

Penyataan yang disiapkan adalah cara untuk membuat pertanyaan pangkalan data dengan lebih selamat dan boleh dipercayai. Idenya adalah bahawa bukannya mengirim pertanyaan mentah ke pangkalan data, pertama-tama kami memberitahu pangkalan data struktur pertanyaan yang akan kami kirimkan. Inilah yang kita maksudkan dengan “menyiapkan” pernyataan. Setelah pernyataan disiapkan, kami menyampaikan maklumat sebagai input parametrized sehingga pangkalan data dapat “mengisi jurang” dengan memasukkan input ke struktur pertanyaan yang kami kirim sebelumnya. Ini menghilangkan kekuatan khas yang mungkin dimiliki input, menyebabkannya diperlakukan sebagai pemboleh ubah belaka (atau muatan, jika anda mau) dalam keseluruhan proses. Berikut adalah pernyataan yang disediakan:

<?php
$ nama pelayan = "localhost";
$ nama pengguna = "nama pengguna";
$ kata laluan = "kata laluan";
$ dbname = "myDB";

// Buat sambungan
$ conn = mysqli baru ($ servername, $ username, $ password, $ dbname);

// Periksa sambungan
jika ($ samb->sambung_ralat) {
mati ("Sambungan gagal: " . $ samb->connect_error);
}

// sediakan dan ikat
$ stmt = $ samb->sediakan ("INSERT INTO MyGuests (nama pertama, nama belakang, e-mel) NILAI (?,?,?)");
$ stmt->mengikat_param ("sss", $ nama pertama, $ nama belakang, $ e-mel);

// tetapkan parameter dan laksanakan
$ nama pertama = "John";
$ nama akhir = "Doe";
$ e-mel = "[dilindungi e-mel]";
$ stmt->laksanakan ();

$ nama pertama = "Maria";
$ nama akhir = "Moe";
$ e-mel = "[dilindungi e-mel]";
$ stmt->laksanakan ();

$ nama pertama = "Julie";
$ nama akhir = "Dooley";
$ e-mel = "[dilindungi e-mel]";
$ stmt->laksanakan ();

gema "Rekod baru berjaya dibuat";

$ stmt->tutup ();
$ samb->tutup ();
?>

Saya tahu prosesnya terdengar tidak rumit jika anda baru dalam penyataan yang disediakan, tetapi konsepnya sepadan dengan usaha. Inilah pengenalan yang baik untuknya.

Bagi mereka yang sudah biasa dengan peluasan PDO PHP dan menggunakannya untuk membuat pernyataan yang sudah siap, saya mempunyai sedikit nasihat.

Amaran: Berhati-hati semasa menyediakan PDO

Semasa menggunakan PDO untuk akses pangkalan data, kita dapat tersembunyi dalam rasa aman yang salah. “Ah, saya menggunakan PDO. Sekarang saya tidak perlu memikirkan perkara lain ”- begitulah cara pemikiran kita secara umum. Memang benar bahawa PDO (atau pernyataan yang disediakan MySQLi) sudah cukup untuk mencegah segala macam serangan suntikan SQL, tetapi anda mesti berhati-hati semasa menyiapkannya. Adalah biasa untuk hanya menyalin-kod kod dari tutorial atau dari projek terdahulu anda dan meneruskannya, tetapi tetapan ini dapat mengurungkan semuanya:

$ dbSambungan->setAttribute (PDO :: ATTR_EMULATE_PREPARES, benar);

Apa yang dilakukan oleh tetapan ini adalah untuk memberitahu PDO untuk meniru pernyataan yang telah disiapkan daripada benar-benar menggunakan ciri penyataan yang disediakan dalam pangkalan data. Oleh itu, PHP menghantar rentetan pertanyaan mudah ke pangkalan data walaupun kod anda kelihatan seperti membuat pernyataan yang siap dan menetapkan parameter dan semua itu. Dengan kata lain, anda terdedah kepada suntikan SQL seperti sebelumnya. ��

Penyelesaiannya mudah: pastikan peniruan ini disetel ke palsu.

$ dbSambungan->setAttribute (PDO :: ATTR_EMULATE_PREPARES, false);

Sekarang skrip PHP terpaksa menggunakan pernyataan yang disiapkan pada tingkat pangkalan data, mencegah segala macam suntikan SQL.

Mencegah penggunaan WAF

Adakah anda tahu anda juga dapat melindungi aplikasi web dari suntikan SQL dengan menggunakan WAF (firewall aplikasi web)?

Baiklah, bukan hanya suntikan SQL tetapi banyak lagi kelemahan 7 lapisan seperti skrip rentas laman web, pengesahan yang rosak, pemalsuan silang laman, pendedahan data, dan lain-lain. Sama ada anda boleh menggunakan hos diri seperti Mod Security atau berasaskan awan seperti berikut.

Suntikan SQL dan kerangka PHP moden

Suntikan SQL sangat biasa, sangat mudah, mengecewakan dan sangat berbahaya sehingga semua kerangka web PHP moden dilengkapi dengan tindakan balas. Sebagai contoh, di WordPress, kita mempunyai $ wpdb->persiapkan () fungsi, sedangkan jika anda menggunakan kerangka MVC, ia berfungsi dengan baik dan anda tidak perlu memikirkan untuk mengelakkan suntikan SQL. Agak menjengkelkan bahawa di WordPress anda harus menyediakan pernyataan secara eksplisit, tetapi hei, inilah WordPress yang sedang kita bicarakan. ��

Bagaimanapun, maksud saya adalah, generasi pemaju web moden tidak perlu memikirkan suntikan SQL, dan akibatnya, mereka tidak menyedari kemungkinannya. Oleh itu, walaupun mereka membiarkan satu pintu belakang terbuka dalam aplikasi mereka (mungkin itu adalah parameter pertanyaan $ _GET dan tabiat lama untuk menendang pertanyaan kotor), hasilnya boleh menjadi bencana. Oleh itu, lebih baik meluangkan masa untuk menyelami asas-asasnya dengan lebih mendalam.

Kesimpulannya

SQL Injection adalah serangan yang sangat jahat pada aplikasi web tetapi mudah dielakkan. Seperti yang kita lihat dalam artikel ini, berhati-hati ketika memproses input pengguna (omong-omong, SQL Injection bukan satu-satunya ancaman yang menangani input pengguna) dan bertanya kepada pangkalan data yang ada di dalamnya. Walaupun begitu, kami tidak selalu bekerja dalam keselamatan kerangka web, jadi lebih baik kita mengetahui jenis serangan ini dan tidak perlu melakukannya.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Комментариев нет, будьте первым кто его оставит

    Комментарии закрыты.

    Adblock
    detector