Panduan Pasukan Lucee MY

Keselamatan Aplikasi Web CFML: XSS, CSRF, Header Keselamatan dan Pengesahan Input

Panduan keselamatan aplikasi web CFML: cegah XSS dengan encodeForHTML, CSRF dengan token, header keselamatan, dan pengesahan input merujuk cheat sheet OWASP.

Keselamatan Aplikasi Web CFML: XSS, CSRF, Header Keselamatan dan Pengesahan Input
0
Kandungan

Keselamatan Aplikasi Web CFML: XSS, CSRF, Header Keselamatan dan Pengesahan Input

Keselamatan aplikasi web dalam CFML berpusat pada empat perkara: enkod output yang betul untuk menangani XSS, token CSRF untuk mengesahkan asal permintaan, header keselamatan untuk mengawal kelakuan pelayar, dan pengesahan input sebelum sebarang data dipercayai. Lucee menyediakan alat untuk kesemuanya, terutamanya keluarga fungsi encodeFor* yang diambil daripada OWASP ESAPI. Panduan ini menyusun kesemua lapisan itu dalam satu rujukan praktikal dengan checklist yang boleh anda semak terus.

Peta Ancaman dan Kedudukan OWASP

Sebelum menulis kod, fahami dahulu apa yang anda pertahankan. OWASP mengekalkan senarai Top 10 risiko aplikasi web yang dikemas kini, dan suntikan, termasuk suntikan SQL dan XSS, kekal dalam kategori Injection. XSS berlaku apabila data pengguna dipaparkan tanpa enkod dan menjadi kod yang boleh dilaksanakan. CSRF berlaku apabila penyerang memujuk pelayar pengguna yang telah log masuk untuk menghantar permintaan yang mengubah keadaan tanpa disedari. Kedua-duanya berbeza dari segi punca dan ubat, jadi jangan cuba selesaikan kedua-duanya dengan satu teknik sahaja.

Cross-Site Scripting (XSS) dan Enkod Output

XSS berpunca daripada satu tabiat buruk: menulis data yang tidak dipercayai terus ke dalam halaman. Prinsip pertahanan OWASP ialah enkod output mengikut konteks, iaitu data mesti dienkod dengan cara yang betul untuk tempat ia muncul, sama ada teks HTML, atribut, JavaScript, CSS atau URL. Dalam CFML, anda tidak perlu menulis fungsi enkod sendiri kerana Lucee menyediakan fungsi khusus untuk setiap konteks:

<cfoutput>
    <p>Nama: #encodeForHTML(form.name)#</p>
    <input type="text" value="#encodeForHTMLAttribute(form.name)#">
</cfoutput>

Contoh di atas menunjukkan dua konteks yang berbeza. Untuk teks di antara tag, gunakan encodeForHTML(). Untuk nilai di dalam atribut, gunakan encodeForHTMLAttribute(), kerana ia turut mengendalikan petikan dengan cara yang khusus untuk konteks atribut. Jika anda menulis data ke dalam blok JavaScript, gunakan encodeForJavaScript() pula. Menggunakan encodeForHTML() di semua tempat adalah satu kesilapan lazim, kerana satu fungsi tidak melindungi semua konteks.

Fungsi encodeFor Mengikut Konteks

Dokumentasi Lucee menyatakan setiap fungsi ini bertujuan untuk output selamat bagi menghentikan serangan XSS, dan semuanya menyokong parameter canonicalize untuk mengesan input yang dikodkan berganda sebelum enkod dilakukan. Jadual berikut memetakan konteks kepada fungsi yang betul:

KonteksFungsiContoh penggunaan
Teks HTMLencodeForHTML()#encodeForHTML(nama)#
Atribut HTMLencodeForHTMLAttribute()value="#encodeForHTMLAttribute(nama)#"
JavaScriptencodeForJavaScript()var n = "#encodeForJavaScript(nama)#";
CSSencodeForCSS()nilai dalam blok style
URLencodeForURL()nilai dalam parameter query

Perhatikan bahawa encodeForURL() diterangkan sebagai output selamat dalam URL, manakala yang lain secara khusus menyebut menghentikan XSS. Gunakan jadual ini sebagai rujukan cepat setiap kali anda menulis output, dan jangan campur konteks. Untuk memahami dari mana data seperti form dan url datang, lihat memahami scope CFML.

Cross-Site Request Forgery (CSRF) dan Token

CSRF mengeksploitasi kepercayaan pelayar terhadap sesi yang aktif. Pertahanan standard OWASP ialah pola token penyegerak, iaitu token rahsia, unik dan sukar dijangka yang dijana dengan kaedah selamat dan dihantar bersama setiap borang. Pelayar penyerang tidak dapat membaca token ini, jadi permintaan palsu akan gagal. Dalam Lucee, jana token dengan generateSecretKey() dan simpan dalam skop sesi:

// Application.cfc, semasa sesi bermula
if (!structKeyExists(session, "csrfToken")) {
    session.csrfToken = generateSecretKey("AES");
}

Kemudian masukkan token sebagai medan tersembunyi dalam borang, dan sahkan semasa memproses permintaan:

<form method="post">
    <input type="hidden" name="csrfToken" value="#encodeForHTMLAttribute(session.csrfToken)#">
    <input type="text" name="email">
    <button type="submit">Simpan</button>
</form>
// Semasa memproses permintaan POST
if (!structKeyExists(form, "csrfToken") || form.csrfToken != session.csrfToken) {
    cfheader(statusCode = 403);
    abort;
}

Atribut kuki SameSite turut disyorkan sebagai lapisan pertahanan tambahan, tetapi OWASP mengingatkan ia tidak menggantikan token CSRF dalam kebanyakan penggunaan. Untuk asas pengurusan sesi yang menjadi tempat token ini tinggal, rujuk pengurusan sesi session.

Header Keselamatan dengan cfheader

Header respons HTTP mengawal cara pelayar melayan halaman anda, dan banyak daripadanya menutup kelas serangan tertentu. Tag cfheader dalam Lucee menjana header respons HTTP tersuai, jadi anda boleh menetapkannya secara berpusat dalam Application.cfc supaya setiap halaman mewarisinya:

// Dalam Application.cfc, fungsi onRequestStart()
cfheader(name = "X-Frame-Options", value = "DENY");
cfheader(name = "X-Content-Type-Options", value = "nosniff");
cfheader(name = "Referrer-Policy", value = "strict-origin-when-cross-origin");
cfheader(name = "Strict-Transport-Security", value = "max-age=31536000; includeSubDomains");

Jadual berikut meringkaskan header yang paling berguna dan tujuan masing-masing:

HeaderNilai disyorkanTujuan
X-Frame-OptionsDENYHalang halaman dipaparkan dalam frame, cegah clickjacking
X-Content-Type-OptionsnosniffHalang pelayar meneka jenis MIME
Referrer-Policystrict-origin-when-cross-originHad maklumat rujukan yang dihantar
Strict-Transport-Securitymax-age besar, includeSubDomainsPaksa sambungan HTTPS
Content-Security-Policydasar allowlistSekat sumber kandungan yang dibenarkan

Content-Security-Policy ialah alat yang berkuasa tetapi OWASP menasihatkan ia sebagai lapisan tambahan, bukan pertahanan utama, kerana mudah tersilap konfigurasi. Header X-XSS-Protection pula ialah ciri lama pelayar Internet Explorer yang sudah tidak relevan dalam pelayar moden, jadi anda tidak perlu menetapkannya. Tetapkan header ini di satu tempat, bukan berulang dalam setiap templat. Untuk memahami di mana Application.cfc sesuai dalam kitaran hidup aplikasi, baca memahami application.cfc.

Pengesahan Input: Jangan Percaya Sebelum Sahkan

Enkod output menghalang data daripada menjadi kod, tetapi ia tidak menjadikan data itu betul. Pengesahan input memastikan nilai yang masuk menepati bentuk yang anda jangkakan sebelum ia diproses atau disimpan. Sahkan panjang, jenis dan format seawal mungkin, dan tolak dengan jelas apabila nilai gagal:

// Sahkan sebelum menyimpan
if (len(trim(form.email)) > 254 || !isValid("email", form.email)) {
    // Kembalikan mesej ralat kepada pengguna
    throw(type = "invalidInput", message = "Alamat e-mel tidak sah.");
}

Fungsi isValid() menyokong banyak format, termasuk email, date, integer dan uuid. Jangan sekali-kali bergantung pada pengesahan di sebelah pelayar sahaja, kerana penyerang boleh memintas JavaScript dan menghantar permintaan terus ke pelayan. Pengesahan mesti berlaku pada pelayan, iaitu tempat anda mempunyai kawalan penuh ke atas data. Gabungkan pengesahan input di pintu masuk dengan enkod output di pintu keluar, dan anda menutup dua hujung aliran data. Untuk pertanyaan pangkalan data, lapisan ketiga ialah parameterisasi, yang dibincangkan secara terperinci dalam panduan cfquery dan cfqueryparam.

Checklist Keselamatan CFML

Gunakan senarai ini untuk menyemak aplikasi anda:

  1. Semua output data pengguna menggunakan encodeFor* mengikut konteks yang betul.
  2. Setiap borang yang mengubah keadaan membawa token CSRF dan disahkan pada pelayan.
  3. Header keselamatan ditetapkan secara berpusat dalam Application.cfc.
  4. Semua pertanyaan pangkalan data menggunakan parameter, bukan cantuman rentetan.
  5. Semua input pengguna disahkan jenis, panjang dan format sebelum digunakan.
  6. Kuki sesi ditandakan dengan atribut selamat yang sesuai.

Tiada satu teknik yang menjadikan aplikasi kebal, tetapi gabungan enam perkara di atas menutup sebahagian besar laluan serangan yang paling lazim. Jika anda masih memilih antara gaya penulisan untuk melaksanakan lapisan ini, perbezaan gaya tag dan skrip boleh membantu.

Soalan Lazim (FAQ)

Apakah fungsi utama untuk mencegah XSS dalam CFML?

Gunakan encodeForHTML() untuk teks HTML, encodeForHTMLAttribute() untuk nilai atribut, dan encodeForJavaScript() untuk output dalam JavaScript. Pilih fungsi mengikut konteks tempat data dipaparkan.

Bagaimana token CSRF mencegah serangan?

Token ialah nilai rahsia dan sukar dijangka yang disimpan dalam sesi dan dihantar bersama borang. Permintaan daripada tapak penyerang tidak membawa token ini, jadi pelayan boleh menolaknya.

Adakah header keselamatan mencukupi untuk melindungi aplikasi?

Tidak. Header seperti Content-Security-Policy ialah lapisan tambahan. Enkod output, token CSRF dan parameterisasi pertanyaan masih diperlukan sebagai pertahanan utama.

Apakah beza pengesahan input dan enkod output?

Pengesahan input menyemak bahawa nilai yang masuk menepati format yang dijangkakan sebelum diproses. Enkod output memastikan nilai yang keluar tidak boleh menjadi kod boleh laksana apabila dipaparkan.

Adakah fungsi encodeFor ini khusus untuk Lucee?

Fungsi ini datang daripada OWASP ESAPI dan tersedia dalam Lucee sebagai keluarga encodeFor*. Ia bukan ciri proprietari, tetapi penamaan dan kelakuan asasnya mengikut piawaian ESAPI.

Sumber

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk