Ralat kebenaran fail dan keselamatan dalam Lucee: 403, fail hilang dan tulisan kosong
Kenapa POST dibalas 403, fail tidak dijumpai walaupun ada, sudo menulis fail kosong, gelung melaporkan dilangkau, dan admin menolak walaupun kata laluan betul.
Kandungan
- Ralat kebenaran fail dan keselamatan dalam Lucee: 403, fail hilang dan tulisan kosong
- Kenapa POST saya dibalas 403 tanpa mesej?
- Kenapa fail tidak dijumpai walaupun ia ada?
- Kenapa arahan sudo menulis fail kosong?
- Kenapa gelung saya melaporkan setiap fail dilangkau?
- Kenapa panel pentadbir menolak saya walaupun kata laluan betul?
- Kenapa fail .env mesti disekat pada lapisan pelayan?
- Corak di sebalik lima ralat ini
- Soalan Lazim
- Sumber
Ralat kebenaran fail dan keselamatan dalam Lucee: 403, fail hilang dan tulisan kosong
Ralat kebenaran jarang memberi mesej yang berguna. Ada yang hanya membalas 403 tanpa butiran, ada yang melaporkan fail tidak wujud sedangkan fail itu ada, dan ada yang menulis fail kosong tanpa sebarang ralat.
Lima kes di bawah ini berlaku pada lapisan antara pengguna, pelayan web dan sistem fail. Setiap satu pernah menyebabkan kerja yang kelihatan berjaya tetapi sebenarnya tidak berlaku.
Kenapa POST saya dibalas 403 tanpa mesej?
Mesej:
403 Forbidden
Dalam aplikasi CFML yang mempunyai perlindungan CSRF, setiap POST mesti membawa token sesi. Borang yang tidak menghantar token akan ditolak sebelum kod anda berjalan.
Gejala yang biasa: borang berfungsi pada satu halaman, gagal pada halaman lain. Puncanya bukan sesi, tetapi medan tersembunyi yang tiada dalam satu templat.
Pembetulan: pastikan setiap borang POST membawa token yang sama dengan sesi.
<input type="hidden" name="csrf" value="#session.csrf#">
Perangkap yang lebih halus: token itu dicetak di luar <cfoutput>, jadi nilainya kosong walaupun medan itu ada.
<input type="hidden" name="csrf" value="#session.csrf#">
Di atas kelihatan betul dalam editor, tetapi apabila ia berada di luar <cfoutput>, Lucee menghantar teks itu secara literal dan pelayar menghantar rentetan #session.csrf# sebagai token. Hasilnya 403, dan penyemak rangkaian menunjukkan medan itu memang ada.
Pembetulan: balut dengan <cfoutput> atau gunakan pembantu yang mencetak nilai.
<cfoutput>
<input type="hidden" name="csrf" value="#session.csrf#">
</cfoutput>
Kenapa fail tidak dijumpai walaupun ia ada?
Mesej:
File not found: /var/www/laporan.csv
Fail itu wujud, tetapi bukan untuk pengguna yang menjalankan Lucee. Dalam pemasangan multi-tenant, setiap laman mempunyai pengguna sistem sendiri, dan fail yang dicipta oleh root tidak boleh dibaca oleh pengguna itu.
Semak pemilik dan kebenaran sebelum menyalahkan laluan.
ls -l /var/www/laporan.csv
Kalau pemiliknya root dan modnya 600, Lucee tidak boleh membacanya. Pembetulan: beri pemilik kepada pengguna slot.
chown <pengguna-slot>:<pengguna-slot> /var/www/laporan.csv
chmod 640 /var/www/laporan.csv
Perkara yang sama berlaku pada folder: Lucee memerlukan kebenaran x untuk masuk ke folder, bukan hanya r. Folder 700 milik root menghalang Lucee walaupun fail di dalamnya 644.
Amalan yang baik: tulis fail sebagai pengguna yang sama yang akan membacanya, dan elak menulis ke dalam pokok aplikasi daripada skrip pentadbir.
Kenapa arahan sudo menulis fail kosong?
Corak ini menipu kerana arahan itu kelihatan berjaya.
sudo cp -a data.csv /root/backup/data.csv
sudo cat laporan > /root/backup/laporan.txt
Baris pertama berjaya kerana sudo menjalankan cp. Baris kedua gagal kerana pengalihan > dilakukan oleh shell anda sendiri, bukan oleh sudo. Shell itu berjalan sebagai pengguna biasa, jadi ia tidak boleh menulis ke /root/backup, dan fail tidak pernah dicipta.
Yang lebih buruk: kalau ralat itu dialihkan ke /dev/null, tiada apa yang kelihatan.
Pembetulan: tulis ke lokasi yang anda boleh tulis, kemudian pindahkan.
cat laporan > /tmp/laporan.txt
sudo mv /tmp/laporan.txt /root/backup/laporan.txt
Atau jalankan keseluruhan arahan di dalam shell root.
sudo bash -c 'cat laporan > /root/backup/laporan.txt'
Selepas menulis, sahkan artifak itu: saiz, ls -l, dan untuk arkib, gzip -t. Jangan percaya kod keluar arahan sahaja.
Kenapa gelung saya melaporkan setiap fail dilangkau?
Corak yang selalu berlaku dalam skrip salinan:
for f in "${fail[@]}"; do
if [ -f "$f" ]; then
cp "$f" /dest/
else
echo "dilangkau: $f"
fi
done
Kalau gelung ini berjalan sebagai pengguna biasa dan fail itu milik pengguna lain, ujian [ -f ] gagal walaupun fail wujud. Setiap fail dilaporkan "dilangkau", gelung keluar dengan kod 0, dan salinan kelihatan selesai sedangkan sifar fail berpindah.
Pembetulan: jalankan gelung di dalam shell root, dan sahkan di destinasi.
sudo bash -c 'for f in "$@"; do cp "$f" /dest/; done' -- "${fail[@]}"
Selepas itu, semak fail baharu di destinasi, bukan kod keluar.
ls -l /dest/ | head
Kenapa panel pentadbir menolak saya walaupun kata laluan betul?
Kalau panel pentadbir dilindungi senarai IP, setiap permintaan dari alamat lain dibalas 403 sebelum kata laluan diperiksa. Ini sengaja: ia mengurangkan permukaan serangan, dan ia juga menyebabkan salah faham kerana mesejnya sama seperti kata laluan salah.
Semak dari mana permintaan itu datang.
curl -s -o /dev/null -w '%{http_code}\n' https://contoh.my/admin/log-masuk
Kalau ia 403 pada rangkaian yang tidak disenaraikan, itu bukan masalah kata laluan. Uji dari alamat yang dibenarkan, atau tambah alamat anda sendiri dengan sedar dan rekodkan perubahan itu.
Amalan yang baik: asingkan mesej untuk "IP tidak dibenarkan" daripada "kata laluan salah", supaya orang yang sah tidak membuang masa menetapkan semula kata laluan.
Kenapa fail .env mesti disekat pada lapisan pelayan?
Ini bukan ralat, tetapi ia punca kebocoran yang paling biasa. Pengimbas automatik menghantar ratusan permintaan ke /.env, /.env.local dan /.env.production setiap hari, dan satu jawapan 200 sudah cukup untuk membocorkan kunci pangkalan data serta kunci API.
Sekat pada lapisan pelayan, bukan pada aplikasi.
location ~ /\.(?!well-known) {
deny all;
return 404;
}
Contoh di atas ialah untuk nginx. Dalam Traefik, sekatan jenis ini dibuat melalui middleware atau dengan memastikan fail itu tidak berada dalam webroot langsung. Yang paling selamat: jangan letak .env dalam folder yang dihidangkan.
Uji selepas memasang sekatan, dan uji dari luar, bukan dari dalam pelayan.
curl -s -o /dev/null -w '%{http_code}\n' https://contoh.my/.env
Sasaran ialah 404 atau 403, bukan 200 dan bukan 500.
Corak di sebalik lima ralat ini
Semua lima ralat ini berlaku kerana dua perkara yang berbeza bercakap tentang perkara yang sama: pengguna yang menjalankan arahan, dan pengguna yang menjalankan aplikasi.
Apabila satu fail tidak dijumpai, tanya siapa yang membacanya. Apabila satu tulisan gagal tanpa ralat, tanya siapa yang menulis. Apabila satu permintaan ditolak, tanya di lapisan mana ia ditolak.
Tiga soalan itu menyelesaikan sebahagian besar masalah kebenaran, dan ia lebih cepat daripada membaca semula kod.
Tabiat yang membantu: setiap kali satu fail dicipta oleh skrip pentadbir, tetapkan pemiliknya pada saat yang sama. Menunggu sehingga aplikasi gagal bermakna anda akan mencari punca di tempat yang salah, biasanya dalam kod aplikasi, sedangkan masalahnya pada sistem fail. Satu baris chown selepas penulisan menghapuskan keseluruhan kelas ralat ini. Amalan yang sama berguna untuk folder muat naik: tetapkan pemilik folder itu sekali, dan biarkan aplikasi menulis di dalamnya tanpa campur tangan pentadbir kemudian.
Ralat yang datang daripada kod memberi mesej yang menyebut fail dan baris, dan ia lebih mudah dikesan kerana punca dan gejalanya berada di tempat yang sama. Ralat kebenaran pula tidak menyebut siapa yang salah, jadi ia memerlukan soalan yang berbeza.
Soalan Lazim
Kenapa 403 dan bukan 401? 401 bermaksud anda belum disahkan. 403 bermaksud permintaan itu ditolak walaupun identiti diketahui, contohnya kerana tiada token CSRF atau IP tidak dibenarkan.
Boleh saya matikan CSRF untuk satu borang? Boleh, tetapi hanya untuk laluan yang membawa pengesahan sendiri, seperti endpoint penyelenggaraan dengan token. Jangan matikan untuk borang awam.
Kenapa chmod 777 tidak menyelesaikan masalah? Kerana ia memberi kebenaran kepada semua pengguna, termasuk proses yang tidak sepatutnya menulis. Ia juga menyembunyikan punca sebenar, iaitu pemilik fail yang salah.
Adakah senarai IP menggantikan kata laluan? Tidak. Kedua-duanya lapisan berbeza. Senarai IP menghalang permintaan sampai ke borang, kata laluan mengesahkan orang yang sampai.
Bagaimana menguji sekatan .env tanpa menyentuh pelayan hidup?
Uji pada rig atau pelayan ujian dengan fail contoh yang tidak mengandungi kunci sebenar. Jangan cipta .env palsu pada pelayan produksi kerana pengimbas akan menjumpainya.
Sumber
- Ralat kompilasi: ralat-kompilasi-cfml
- Halaman 500: ralat-http-500-lucee
- Ralat runtime skop: ralat-runtime-cfml-skop
- Ralat pangkalan data dan mel: ralat-pangkalan-data-mel-lucee