Apakah ada fungsi catchall di suatu tempat yang berfungsi dengan baik untuk membersihkan input pengguna untuk injeksi SQL dan serangan XSS, sementara masih memungkinkan jenis tag HTML tertentu?
php
security
xss
sql-injection
user-input
Brent
sumber
sumber
select * from users where name='$name'
, maka tidak masalah jika Anda menggunakan PDO atau MySQLi atau MySQL. Anda masih dalam bahaya. Anda harus menggunakan kueri parametrized atau, jika Anda harus, menggunakan mekanisme melarikan diri pada data Anda, tetapi itu jauh lebih disukai.Jawaban:
Ini adalah kesalahpahaman umum bahwa input pengguna dapat difilter. PHP bahkan memiliki "fitur" yang sekarang sudah tidak digunakan lagi, yang disebut kutipan ajaib , yang dibangun berdasarkan ide ini. Ini omong kosong. Lupakan penyaringan (atau pembersihan, atau apa pun orang menyebutnya).
Apa yang harus Anda lakukan, untuk menghindari masalah, cukup sederhana: setiap kali Anda memasukkan string ke dalam kode asing, Anda harus menghindarinya, sesuai dengan aturan bahasa itu. Misalnya, jika Anda menyematkan string dalam beberapa SQL yang menargetkan MySQL, Anda harus melarikan diri string dengan fungsi MySQL untuk tujuan ini (
mysqli_real_escape_string
). (Atau, dalam hal database, menggunakan pernyataan yang disiapkan adalah pendekatan yang lebih baik, bila mungkin.)Contoh lain adalah HTML: Jika Anda menanamkan string dalam markup HTML, Anda harus menghindarinya
htmlspecialchars
. Ini berarti bahwa setiapecho
atauprint
pernyataan harus menggunakanhtmlspecialchars
.Contoh ketiga bisa berupa perintah shell: Jika Anda akan menanamkan string (seperti argumen) ke perintah eksternal, dan memanggilnya dengan
exec
, maka Anda harus menggunakanescapeshellcmd
danescapeshellarg
.Dan seterusnya dan seterusnya ...
Satu- satunya kasus di mana Anda perlu memfilter data secara aktif, adalah jika Anda menerima input yang telah diformat sebelumnya. Misalnya, jika Anda membiarkan pengguna memposting markup HTML, yang Anda rencanakan untuk ditampilkan di situs. Namun, Anda harus bijaksana untuk menghindari ini di semua biaya, karena tidak peduli seberapa baik Anda menyaringnya, itu akan selalu menjadi lubang keamanan potensial.
sumber
mysql_real_escape_string
sudah usang. Ini dianggap praktik yang baik saat ini untuk menggunakan pernyataan yang disiapkan untuk mencegah injeksi SQL. Jadi beralihlah ke MySQLi atau PDO.Jangan mencoba untuk mencegah injeksi SQL dengan membersihkan data input.
Sebaliknya, jangan izinkan data untuk digunakan dalam membuat kode SQL Anda . Gunakan Pernyataan Disiapkan (yaitu menggunakan parameter dalam kueri templat) yang menggunakan variabel terikat. Ini adalah satu-satunya cara untuk dijamin terhadap injeksi SQL.
Silakan lihat situs web saya http://bobby-tables.com/ untuk lebih lanjut tentang mencegah injeksi SQL.
sumber
Tidak. Anda tidak dapat secara umum memfilter data tanpa konteks apa tujuannya. Terkadang Anda ingin mengambil kueri SQL sebagai input dan terkadang Anda ingin mengambil HTML sebagai input.
Anda perlu memfilter input pada daftar putih - memastikan bahwa data cocok dengan spesifikasi yang Anda harapkan. Maka Anda perlu menghindarinya sebelum menggunakannya, tergantung pada konteks di mana Anda menggunakannya.
Proses melarikan diri data untuk SQL - untuk mencegah injeksi SQL - sangat berbeda dari proses melarikan diri data untuk (X) HTML, untuk mencegah XSS.
sumber
PHP memiliki fungsi filter_input baru yang bagus sekarang, yang misalnya membebaskan Anda dari menemukan 'regex email utama' sekarang karena ada tipe FILTER_VALIDATE_EMAIL bawaan
Kelas filter saya sendiri (menggunakan JavaScript untuk menyorot bidang yang salah) dapat dimulai dengan permintaan ajax atau posting bentuk normal. (lihat contoh di bawah)
Tentu saja, perlu diingat bahwa Anda perlu melakukan kueri sql Anda juga tergantung pada jenis db yang Anda gunakan (mysql_real_escape_string () misalnya, tidak berguna untuk server sql). Anda mungkin ingin menangani ini secara otomatis pada lapisan aplikasi yang sesuai seperti ORM. Juga, seperti disebutkan di atas: untuk menghasilkan ke html, gunakan fungsi khusus php lainnya seperti htmlspecialchars;)
Untuk benar-benar mengizinkan input HTML dengan kelas dan / atau tag yang dilucuti seperti bergantung pada salah satu paket validasi xss khusus. JANGAN MENULIS REGEX ANDA SENDIRI KE PARSE HTML!
sumber
Tidak, tidak ada.
Pertama-tama, injeksi SQL adalah masalah pemfilteran input, dan XSS adalah output yang lolos - jadi Anda bahkan tidak akan menjalankan dua operasi ini pada saat yang sama dalam siklus hidup kode.
Aturan dasar praktis
mysql_real_escape_string()
)strip_tags()
untuk menyaring HTML yang tidak diinginkanhtmlspecialchars()
dan perhatikan parameter ke-2 dan ke-3 di sini.sumber
Untuk mengatasi masalah XSS, lihat Pemurni HTML . Ini cukup dapat dikonfigurasi dan memiliki rekam jejak yang baik.
Adapun serangan injeksi SQL, pastikan Anda memeriksa input pengguna, dan kemudian jalankan meskipun mysql_real_escape_string (). Namun, fungsi ini tidak akan mengalahkan semua serangan injeksi, jadi Anda harus memeriksa data sebelum membuangnya ke string kueri Anda.
Solusi yang lebih baik adalah dengan menggunakan pernyataan yang disiapkan. The perpustakaan PDO dan ekstensi mysqli mendukung ini.
sumber
PHP 5.2 memperkenalkan fungsi filter_var .
Ini mendukung banyak filter SANITIZE, VALIDATE.
http://php.net/manual/en/function.filter-var.php
sumber
Salah satu trik yang dapat membantu dalam keadaan tertentu di mana Anda memiliki halaman seperti
/mypage?id=53
dan Anda menggunakan id dalam klausa WHERE adalah untuk memastikan bahwa id jelas adalah bilangan bulat, seperti:Tapi tentu saja itu hanya memotong satu serangan spesifik, jadi bacalah semua jawaban lainnya. (Dan ya saya tahu bahwa kode di atas tidak bagus, tetapi itu menunjukkan pertahanan spesifik.)
sumber
$id = (int)$_GET['id']
dan$que = sprintf('SELECT ... WHERE id="%d"', $id)
juga baikGunakan Versi Modern MySQL dan PHP.
Setel rangkaian karakter secara eksplisit:
Gunakan rangkaian aman:
Gunakan fungsi spasial:
PDO :: quote () - menempatkan kutipan di sekitar string input (jika diperlukan) dan lolos dari karakter khusus dalam string input, menggunakan gaya kutipan yang sesuai dengan driver yang mendasarinya:
Pernyataan Disiapkan PDO : pernyataan yang dipersiapkan vs MySQLi mendukung lebih banyak driver basis data dan parameter bernama:
mysql_real_escape_string[usang dalam PHP 5.5.0, dihapus dalam PHP 7.0.0].Periksa variabel berisi apa yang Anda harapkan:
Gunakan Fungsi Filter filter_var () - memfilter variabel dengan filter yang ditentukan:
filter yang lebih standar
sumber
Apa yang Anda uraikan di sini adalah dua masalah terpisah:
1) Input pengguna harus selalu dianggap buruk.
Menggunakan pernyataan yang disiapkan, atau / dan memfilter dengan mysql_real_escape_string jelas merupakan suatu keharusan. PHP juga memiliki filter_input bawaan yang merupakan tempat yang baik untuk memulai.
2) Ini adalah topik besar, dan itu tergantung pada konteks data yang dikeluarkan. Untuk HTML ada solusi seperti htmlpurifier di luar sana. sebagai aturan praktis, selalu luput dari apapun yang Anda hasilkan.
Kedua masalah ini terlalu besar untuk dimasukkan ke dalam satu posting, tetapi ada banyak posting yang membahas lebih detail:
Metode keluaran PHP
Output PHP lebih aman
sumber
Jika Anda menggunakan PostgreSQL, input dari PHP dapat diloloskan dengan pg_escape_string ()
Dari dokumentasi ( http://php.net/manual/es/function.pg-escape-string.php ):
sumber
Tidak ada fungsi catchall, karena ada beberapa masalah yang harus diatasi.
SQL Injection - Hari ini, umumnya, setiap proyek PHP harus menggunakan pernyataan yang disiapkan melalui PHP Data Objects (PDO) sebagai praktik terbaik, mencegah kesalahan dari kutipan nyasar serta solusi berfitur lengkap terhadap injeksi . Ini juga cara paling fleksibel & aman untuk mengakses database Anda.
Lihatlah tutorial PDO (Satu-satunya yang tepat) untuk mengetahui hampir semua yang perlu Anda ketahui tentang PDO. (Terima kasih yang tulus kepada kontributor SO teratas, @YourCommonSense, untuk sumber yang hebat tentang subjek ini.)
XSS - Sanitasi data di jalan di ...
Pemurni HTML sudah ada sejak lama dan masih diperbarui secara aktif. Anda dapat menggunakannya untuk membersihkan input berbahaya, sambil tetap mengizinkan daftar putih tag yang murah hati & dapat dikonfigurasi. Berfungsi bagus dengan banyak editor WYSIWYG, tetapi mungkin berat untuk beberapa kasus penggunaan.
Dalam kasus lain, di mana kami sama sekali tidak ingin menerima HTML / Javascript, saya menemukan fungsi sederhana ini bermanfaat (dan telah melewati beberapa audit terhadap XSS):
/* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
XSS - Data membersihkan di jalan keluar ... kecuali jika Anda menjamin data itu benar dibersihkan sebelum Anda menambahkannya ke database Anda, Anda harus membersihkan sebelum menampilkan kepada pengguna Anda, kami dapat memanfaatkan fungsi-fungsi PHP yang berguna:
echo
atauprint
menampilkan nilai yang disediakan pengguna, gunakanhtmlspecialchars
kecuali jika data telah dibersihkan dengan aman dan diizinkan untuk menampilkan HTML.json_encode
adalah cara aman untuk memberikan nilai yang disediakan pengguna dari PHP ke JavascriptApakah Anda memanggil perintah shell eksternal menggunakan
exec()
atausystem()
fungsi, atau kebacktick
operator? Jika demikian, selain SQL Injection & XSS Anda mungkin memiliki masalah tambahan untuk diatasi, pengguna yang menjalankan perintah jahat di server Anda . Anda perlu menggunakanescapeshellcmd
jika Anda ingin melarikan diri dari seluruh perintah ATAUescapeshellarg
untuk menghindari argumen individual.sumber
mb_encode_numericentity
dibahas dalamhtmlspecialchars
tautan di # 3 XSSCara termudah untuk menghindari kesalahan dalam membersihkan input dan melarikan diri data menggunakan kerangka kerja PHP seperti Symfony , Nette dll. Atau bagian dari kerangka kerja itu (mesin templating, lapisan basis data, ORM).
Mesin templating seperti Twig atau Latte memiliki output yang keluar secara default - Anda tidak harus menyelesaikan secara manual jika Anda telah benar-benar keluar dari output Anda tergantung pada konteks (HTML atau bagian Javascript dari halaman web).
Kerangka kerja secara otomatis membersihkan input dan Anda tidak boleh menggunakan variabel $ _POST, $ _GET atau $ _SESSION secara langsung, tetapi melalui mekanisme seperti perutean, penanganan sesi, dll.
Dan untuk lapisan basis data (model) ada kerangka kerja ORM seperti Doctrine atau pembungkus di sekitar PDO seperti Nette Database.
Anda dapat membaca lebih lanjut tentang ini di sini - Apa itu kerangka kerja perangkat lunak?
sumber
Hanya ingin menambahkan bahwa pada subjek keluaran melarikan diri, jika Anda menggunakan php DOMDocument untuk membuat output html Anda maka secara otomatis akan keluar dalam konteks yang benar. Atribut (nilai = "") dan teks bagian dalam <span> tidak sama. Untuk aman terhadap XSS baca ini: OWASP XSS Prevention Cheat Sheet
sumber
Anda tidak pernah membersihkan input.
Anda selalu membersihkan output.
Transformasi yang Anda terapkan pada data untuk membuatnya aman untuk dimasukkan dalam pernyataan SQL benar-benar berbeda dari yang Anda ajukan untuk dimasukkan dalam HTML benar-benar berbeda dari yang Anda ajukan untuk dimasukkan dalam Javascript sama sekali berbeda dari yang Anda ajukan untuk dimasukkan dalam LDIF adalah sama sekali berbeda dari yang Anda terapkan pada inklusi di CSS sama sekali berbeda dari yang Anda terapkan pada inklusi dalam Email ....
Dengan segala cara, validasikan input - putuskan apakah Anda harus menerimanya untuk diproses lebih lanjut atau memberi tahu pengguna bahwa itu tidak dapat diterima. Tapi jangan terapkan perubahan apa pun pada representasi data sampai akan meninggalkan tanah PHP.
Beberapa waktu yang lalu seseorang mencoba untuk menemukan satu ukuran cocok untuk semua mekanisme untuk melarikan diri data dan kami berakhir dengan " magic_quotes " yang tidak melarikan diri dengan baik data untuk semua target keluaran dan menghasilkan instalasi berbeda yang memerlukan kode berbeda untuk bekerja.
sumber
Jangan pernah mempercayai data pengguna.
The
trim()
Menghapus fungsi spasi dan karakter yang telah ditetapkan lainnya dari kedua sisi string.The
stripslashes()
fungsi menghilangkan backslashesThe
htmlspecialchars()
Fungsi mengkonversi beberapa karakter yang telah ditetapkan untuk entitas HTML.Karakter yang ditentukan sebelumnya adalah:
sumber
clean_input
demikian? Mengapa Anda ingin menghapus garis miring?Ada ekstensi filter ( tautan howto , manual ), yang berfungsi dengan baik dengan semua variabel GPC. Ini bukan hal yang ajaib, Anda masih harus menggunakannya.
sumber