Saya memahami bahwa Anda TIDAK PERNAH mempercayai masukan pengguna dari formulir, terutama karena kemungkinan injeksi SQL.
Namun, apakah ini juga berlaku untuk formulir di mana satu-satunya masukan adalah dari dropdown (lihat di bawah)?
Saya menyimpan $_POST['size']
ke Sesi yang kemudian digunakan di seluruh situs untuk menanyakan berbagai database (dengan mysqli
kueri Pilih) dan injeksi SQL apa pun pasti akan membahayakan (mungkin menjatuhkan) mereka.
Tidak ada area untuk input pengguna yang diketik untuk menanyakan database, hanya dropdown.
<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>
php
mysql
mysqli
sql-injection
Compang-camping
sumber
sumber
<select>
masukan Anda . Bahkan pengguna yang sedikit teknis dapat menambahkan opsi tambahan menggunakan konsol browser. jika Anda menyimpan daftar putih array dari nilai-nilai yang tersedia dan membandingkan input dengannya, Anda dapat menguranginya (dan Anda harus melakukannya karena itu mencegah nilai yang tidak diinginkan)Jawaban:
Anda dapat melakukan sesuatu yang sederhana seperti contoh berikut untuk memastikan ukuran yang diposting sesuai dengan yang Anda harapkan.
Kemudian gunakan mysqli_ * jika Anda menggunakan versi php> = 5.3.0 yang seharusnya, untuk menyimpan hasil Anda. Jika digunakan dengan benar ini akan membantu injeksi sql.
sumber
mysqli_real_escape_string
. Juga melarikan diri dengan benar nilai saat mengeluarkannya (misalnya gunakan htmlspecialchars () dalam dokumen HTML).in_array
menjaditrue
untuk perbandingan yang ketat. Saya tidak yakin apa yang bisa salah, tetapi perbandingan longgar cukup unik.Ya, Anda perlu melindungi dari ini.
Izinkan saya menunjukkan alasannya, menggunakan konsol pengembang Firefox:
Jika Anda tidak membersihkan data ini, database Anda akan dihancurkan. (Ini mungkin bukan pernyataan SQL yang benar-benar valid, tapi saya harap saya mengerti maksud saya.)
Hanya karena Anda telah membatasi opsi apa yang tersedia di dropdown Anda tidak berarti Anda telah membatasi data yang dapat saya kirim ke server Anda.
Jika Anda mencoba untuk membatasi ini lebih lanjut menggunakan perilaku di halaman Anda, pilihan saya termasuk menonaktifkan perilaku itu, atau hanya menulis permintaan HTTP kustom ke server Anda yang tetap meniru pengiriman formulir ini. Ada alat yang disebut curl digunakan untuk itu, dan saya pikir perintah untuk mengirimkan injeksi SQL ini akan terlihat seperti ini:
(Ini mungkin bukan perintah curl yang benar-benar valid, tetapi sekali lagi, saya harap saya mengerti maksud saya.)
Jadi, saya akan mengulangi:
JANGAN PERNAH mempercayai masukan pengguna. SELALU lindungi diri Anda.
Jangan berasumsi bahwa masukan pengguna akan aman. Ini berpotensi tidak aman bahkan jika itu datang melalui beberapa cara selain formulir. Tak satu pun dari itu pernah cukup dapat dipercaya untuk melupakan melindungi diri Anda dari injeksi SQL.
sumber
curl
. SELALU membersihkan sisi server masukan !curl
. Orang tidak mengerti bahwa Anda dapat mengirim permintaan HTTP dari mana saja ke mana saja menggunakan format apa pun dan meneruskan nilai apa pun, terserah server untuk memastikan permintaan tersebut valid sebelum memprosesnya.Saat pertanyaan ini diberi tag sql-injection, berikut adalah jawaban mengenai jenis serangan khusus ini:
Seperti yang telah Anda ketahui di komentar, Anda harus menggunakan pernyataan yang disiapkan untuk setiap kueri yang melibatkan data variabel apa pun, tanpa pengecualian .
Terlepas dari barang HTML apa pun!
Penting untuk dipahami bahwa kueri SQL harus diformat dengan benar terlepas dari faktor eksternal apa pun, baik itu input HTML atau apa pun.
Meskipun Anda dapat menggunakan daftar putih yang disarankan dalam jawaban lain untuk tujuan validasi input, hal itu seharusnya tidak memengaruhi tindakan apa pun yang terkait dengan SQL - tindakan tersebut harus tetap sama, tidak peduli apakah Anda memvalidasi input HTML atau tidak. Ini berarti Anda masih harus menggunakan pernyataan yang telah disiapkan saat menambahkan variabel apa pun ke dalam kueri.
Di sini Anda dapat menemukan penjelasan menyeluruh, mengapa pernyataan yang disiapkan adalah suatu keharusan dan bagaimana menggunakannya dengan benar dan di mana mereka tidak berlaku dan apa yang harus dilakukan dalam kasus seperti itu: Panduan Hitchhiker untuk perlindungan SQL Injection
Juga, pertanyaan ini diberi tag mysqli.dll. Sebagian besar secara tidak sengaja, saya kira, tetapi bagaimanapun, saya harus memperingatkan Anda bahwa mysqli mentah bukanlah substitusi yang memadai untuk fungsi mysq_ * lama . Karena jika digunakan dengan gaya lama, itu tidak akan menambah keamanan sama sekali. Meskipun dukungan untuk pernyataan yang disiapkan itu menyakitkan dan merepotkan, sampai-sampai pengguna PHP rata-rata tidak bisa mencobanya sama sekali. Jadi, jika tidak ada ORM atau semacam perpustakaan abstraksi pilihan, maka PDO adalah satu-satunya pilihan Anda.
sumber
random
?Iya.
Siapa pun dapat memalsukan apa pun untuk nilai yang benar-benar dikirim -
JADI, untuk memvalidasi menu dropdown, Anda cukup memeriksa untuk memastikan bahwa nilai yang Anda kerjakan ada di dropdown - sesuatu seperti ini akan menjadi cara terbaik (paling paranoid paling waras):
sumber
Salah satu cara untuk melindungi pengguna yang mengubah drop-down Anda menggunakan konsol adalah dengan hanya menggunakan nilai integer di dalamnya. Kemudian Anda dapat memvalidasi bahwa nilai POST berisi integer, dan menggunakan array untuk mengubahnya menjadi teks bila diperlukan. Misalnya:
Kemudian Anda dapat menggunakan
$size
kueri Anda dengan pengetahuan bahwa itu hanya akan pernah berisiFALSE
atau bilangan bulat.sumber
filter_input
jika bukan pemeriksaan di sisi server? Tidak ada yang dapat memposting apa pun kecuali integer.filter_input
bagian tersebut juga untuk validasi, jika tidak maka akan berguna seperti teko coklat untuk keamanan.Jawaban lainnya sudah mencakup apa yang perlu Anda ketahui. Tapi mungkin membantu untuk menjelaskan lebih lanjut:
Ada DUA HAL yang perlu Anda lakukan:
1. Validasi data formulir.
Seperti yang ditunjukkan oleh jawaban Jonathan Hobbs dengan sangat jelas, pilihan elemen html untuk input formulir tidak melakukan pemfilteran yang dapat diandalkan untuk Anda.
Validasi biasanya dilakukan dengan cara yang tidak mengubah data, tetapi menampilkan formulir lagi, dengan kolom yang ditandai sebagai "Harap perbaiki ini".
Sebagian besar framework dan CMS memiliki pembuat formulir yang membantu Anda melakukan tugas ini. Dan tidak hanya itu, mereka juga membantu melawan CSRF (atau "XSRF"), yang merupakan bentuk serangan lain.
2. Sanitasi / Escape variabel dalam pernyataan SQL ..
.. atau biarkan pernyataan yang telah disiapkan melakukan pekerjaan untuk Anda.
Jika Anda membuat pernyataan SQL (Saya) dengan variabel apa pun, disediakan pengguna atau tidak, Anda perlu keluar dan mengutip variabel ini.
Secara umum, variabel apa pun yang Anda masukkan ke dalam pernyataan MySQL harus berupa string, atau sesuatu yang dapat diubah PHP dengan andal menjadi string yang dapat dicerna oleh MySQL. Seperti, angka.
Untuk string, Anda kemudian perlu memilih salah satu dari beberapa metode untuk melarikan diri dari string, yang berarti, ganti karakter apa pun yang akan memiliki efek samping di MySQL.
Jika Anda berurusan dengan angka, Anda dapat menghilangkan escaping dan tanda kutip (inilah mengapa pernyataan yang disiapkan memungkinkan untuk menentukan tipe).
Penting untuk diketahui bahwa Anda keluar dari variabel untuk pernyataan SQL, dan BUKAN untuk database itu sendiri . Basis data akan menyimpan string asli, tetapi pernyataan tersebut membutuhkan versi lolos.
Apa yang terjadi jika Anda menghilangkan salah satunya?
Jika Anda tidak menggunakan validasi formulir , tetapi Anda membersihkan input SQL, Anda mungkin melihat semua jenis hal buruk terjadi, tetapi Anda tidak akan melihat injeksi SQL! (*)
Pertama, ini dapat membuat aplikasi Anda menjadi status yang tidak Anda rencanakan. Misalnya, jika Anda ingin menghitung usia rata-rata semua pengguna, tetapi satu pengguna memberikan "aljkdfaqer" untuk usia tersebut, penghitungan Anda akan gagal.
Kedua, mungkin ada semua jenis serangan injeksi lain yang perlu Anda pertimbangkan: Misalnya input pengguna dapat berisi javascript atau hal lain.
Masih ada masalah dengan database: Misalnya jika sebuah field (kolom tabel database) dibatasi hingga 255 karakter, dan stringnya lebih panjang dari itu. Atau jika bidang hanya menerima angka, dan Anda mencoba menyimpan string non-numerik sebagai gantinya. Tapi ini bukan "injeksi", ini hanya "merusak aplikasi".
Tetapi, bahkan jika Anda memiliki bidang teks bebas di mana Anda mengizinkan masukan apa pun tanpa validasi sama sekali, Anda masih dapat menyimpan ini ke database begitu saja, jika Anda meloloskan diri dengan benar saat masuk ke pernyataan database. Masalahnya muncul saat Anda ingin menggunakan string ini di suatu tempat.
(*) atau ini akan menjadi sesuatu yang sangat eksotis.
Jika Anda tidak melarikan diri dari variabel untuk pernyataan SQL , tetapi Anda memvalidasi input formulir, Anda masih dapat melihat hal-hal buruk terjadi.
Pertama, Anda berisiko bahwa saat Anda menyimpan data ke database dan memuatnya lagi, itu tidak akan menjadi data yang sama lagi, "hilang dalam terjemahan".
Kedua, ini dapat menghasilkan pernyataan SQL yang tidak valid, dan dengan demikian membuat aplikasi Anda mogok. Misalnya, jika ada variabel yang berisi karakter kutipan atau kutipan ganda, tergantung jenis kutipan yang Anda gunakan, Anda akan mendapatkan pernyataan MySQL yang tidak valid.
Ketiga, masih dapat menyebabkan injeksi SQL.
Jika masukan pengguna Anda dari formulir sudah difilter / divalidasi, injeksi SQl yang disengaja mungkin menjadi kecil kemungkinannya, JIKA masukan Anda dikurangi menjadi daftar opsi yang di-hardcode, atau jika dibatasi untuk angka. Tetapi input teks bebas apa pun dapat digunakan untuk injeksi SQL, jika Anda tidak meng-escape dengan benar variabel dalam pernyataan SQL.
Dan bahkan jika Anda tidak memiliki masukan formulir sama sekali, Anda masih dapat memiliki string dari semua jenis sumber: Membaca dari sistem file, menyalin dari internet, dll. Tidak ada yang dapat menjamin bahwa string ini aman.
sumber
Browser web Anda tidak "tahu" bahwa ia menerima halaman dari php, yang dilihatnya hanyalah html. Dan lapisan http tahu lebih sedikit dari itu. Anda harus dapat menangani hampir semua jenis masukan yang dapat melewati lapisan http (untungnya untuk sebagian besar masukan php sudah memberikan kesalahan). Jika Anda mencoba untuk mencegah permintaan jahat dari mengacaukan db Anda, maka Anda perlu berasumsi bahwa orang di ujung lain tahu apa yang dia lakukan, dan bahwa dia tidak terbatas pada apa yang dapat Anda lihat di browser Anda dalam keadaan normal ( belum lagi apa yang dapat Anda mainkan dengan alat pengembang browser). Jadi ya, Anda perlu memenuhi masukan apa pun dari dropdown Anda, tetapi untuk sebagian besar masukan, Anda dapat memberikan kesalahan.
sumber
Fakta bahwa Anda telah membatasi pengguna untuk hanya menggunakan nilai dari daftar tarik-turun tertentu tidaklah relevan. Seorang pengguna teknis dapat menangkap permintaan http yang dikirim ke server Anda sebelum meninggalkan jaringan mereka, mengubahnya menggunakan alat seperti server proxy lokal, dan kemudian melanjutkannya. Dengan menggunakan permintaan yang diubah, mereka dapat mengirim nilai parameter yang bukan yang telah Anda tentukan di daftar tarik-turun. Pengembang harus memiliki pola pikir bahwa batasan klien seringkali tidak berarti, karena apa pun pada klien dapat diubah. Validasi server diperlukan di setiap titik yang dimasukkan data klien. Penyerang mengandalkan kenaifan pengembang dalam satu-satunya aspek ini.
sumber
Sebaiknya gunakan kueri berparameter untuk memastikan terhadap injeksi SQL. Dalam hal ini tampilan kueri akan menjadi seperti ini:
Saat Anda memberikan kueri seperti di atas dengan teks yang integritasnya belum diverifikasi (input tidak divalidasi di server) dan berisi kode injeksi SQL, itu akan ditangani dengan benar. Dengan kata lain, permintaan tersebut akan mengakibatkan hal seperti ini terjadi di lapisan database:
Ini hanya akan memilih 0 hasil karena mengembalikan yang akan membuat kueri tidak efektif yang benar-benar menyebabkan kerusakan pada database tanpa perlu daftar putih, pemeriksaan verifikasi, atau teknik lain. Harap dicatat bahwa programmer yang bertanggung jawab akan melakukan keamanan berlapis, dan akan sering memvalidasi selain kueri parameterisasi. Namun, ada sedikit alasan untuk tidak membuat parameter kueri Anda dari perspektif kinerja dan keamanan yang ditambahkan oleh praktik ini adalah alasan yang baik untuk membiasakan diri Anda dengan kueri berparameter.
sumber
Apa pun yang dikirimkan dari formulir Anda datang ke server Anda sebagai teks di seluruh kabel. Tidak ada yang menghentikan siapa pun untuk membuat bot untuk meniru klien atau mengetiknya dari terminal jika mereka mau. Jangan pernah berasumsi bahwa karena Anda memprogram klien, klien akan bertindak seperti yang Anda kira. Ini sangat mudah untuk dipalsukan.
Contoh apa yang bisa dan akan terjadi ketika Anda mempercayai klien.
sumber
Seorang hacker dapat melewati browser sepenuhnya, termasuk pemeriksaan form Javascript, dengan mengirimkan permintaan menggunakan Telnet. Tentu saja, dia akan melihat kode halaman html Anda untuk mendapatkan nama field yang harus dia gunakan, tapi sejak saat itu 'semuanya berjalan' untuknya. Jadi, Anda harus memeriksa semua nilai yang dikirimkan di server seolah-olah tidak berasal dari halaman html Anda.
sumber