Panduan Pasukan Lucee MY

Session fixation dalam Lucee: id sesi yang diterima daripada penyerang

Session fixation dalam Lucee diuji pada rig 7.1: cfid daripada URL diterima tanpa semakan, sessionRotate selepas log masuk menutupnya, kuki ketat disahkan.

Session fixation dalam Lucee: id sesi yang diterima daripada penyerang
0
Kandungan

Session fixation dalam Lucee: id sesi yang diterima daripada penyerang

Jawapan pantas: Session fixation berlaku apabila penyerang menetapkan id sesi lebih awal, lalu menunggu mangsa log masuk ke dalam sesi yang idnya penyerang sudah tahu. Pada Lucee 7.1.1.17-RC, id sesi yang dihantar melalui URL bentuk ?cfid=<uuid>&cftoken=0 diterima seadanya dan data sesi disimpan di bawah id itu. Satu panggilan sessionRotate() selepas kelayakan disahkan menukar id dan mengekalkan data, sementara id lama menjadi sesi kosong.

Apa itu session fixation, dan kenapa ia berbahaya dalam CFML?

Dalam serangan session fixation, penyerang tidak mencuri sesi sesiapa. Dia menetapkan id sesi terlebih dahulu, kemudian memujuk mangsa menggunakan id itu. Apabila mangsa log masuk, pelayan menyimpan status log masuk ke dalam sesi yang sudah wujud, iaitu sesi yang idnya penyerang simpan sejak awal.

Perbezaannya dengan pencurian sesi penting. Pencurian sesi memerlukan kuki mangsa terbaca, contohnya melalui XSS atau rangkaian tidak disulitkan. Session fixation hanya memerlukan satu pautan yang menetapkan id terlebih dahulu. Dalam CFML, id sesi ialah nilai yang dihantar klien dan diterima enjin seperti parameter lain, dan secara lalai tiada apa-apa yang menyemaknya untuk anda. Halaman keselamatan aplikasi web CFML menerangkan cara XSS dan sesi saling melengkapi; halaman ini menguji sisi sesi itu sendiri.

Bagaimana Lucee mengenal pasti sesi dalam mod cfml?

Pemeriksaan pada rig ujian dengan imej lucee/lucee:7.1.1.17-RC menunjukkan bentuk yang agak berbeza daripada tanggapan lama CFID dan CFTOKEN. Permintaan pertama tanpa kuki menerima dua kuki, dan cfid membawa satu UUID sementara cftoken sentiasa 0:

Set-Cookie: cfid=c53bc0c6-0e1f-40f1-8a2b-3aa4039a068f;Path=/;Expires=Sun, 29-Oct-2056 06:52:52 GMT;HttpOnly;SameSite=Lax
Set-Cookie: cftoken=0;Path=/;Expires=Sun, 29-Oct-2056 06:52:52 GMT;HttpOnly;SameSite=Lax

Tiga perkara boleh dibaca daripada baris itu. Kuki sesi lalai sudah HttpOnly dan SameSite=Lax, jadi ia tidak boleh dibaca JavaScript dan tidak dihantar dalam permintaan silang tapak. Tarikh luputnya hampir tiga puluh tahun, jadi kuki itu kekal walaupun pelayar ditutup. Dan cftoken tidak lagi rawak, ia 0 pada setiap sesi yang diuji, jadi satu-satunya nilai yang mengenal pasti sesi ialah cfid.

Di dalam skop session, Lucee meletakkan cfid, cftoken, sessionid, urltoken, timecreated dan lastvisit. Fungsi getSessionID() yang biasa digunakan dalam ColdFusion pula tidak ada:

Message: No matching function [GETSESSIONID] found

Jadi dalam kod Lucee 7, baca session.cfid dan bukan getSessionID(). Dalam mod sesi j2ee pula enjin menghantar JSESSIONID dan session.cfid tidak wujud, jadi pastikan kod log anda sepadan dengan mod sesi yang dipilih.

Adakah Lucee menerima id sesi yang datang daripada URL?

Ya, dan itulah penemuan utama ujian ini. Satu UUID yang tidak pernah wujud dihantar sebagai parameter URL, dan enjin mencipta sesi baharu di bawah id itu, mengembalikannya dalam Set-Cookie, kemudian menyimpan data sesi di bawahnya pada permintaan berikutnya. Ringkasan ujian dengan curl dan balang kuki berasingan:

PermintaanNilai yang dihantarHasil yang diukur
UUID tidak dikenali melalui URL?cfid=22222222-...&cftoken=0Diterima, Set-Cookie memantulkan id yang sama, data terkumpul pada permintaan kedua
UUID tidak dikenali melalui kukiCookie: cfid=99999999-...Diterima, data terkumpul
Nilai bukan UUID melalui URL atau kukicfid=abc123Ditolak, kuki lama dipadam, UUID baharu dikeluarkan
Kuki sah dihantar berulangcfid yang samaId tidak berubah antara permintaan

Baris ketiga menunjukkan enjin menyemak bentuk nilai, bukan asalnya. Penyerang tidak perlu memujuk enjin menerima sebarang rentetan; dia hanya perlu menghasilkan UUID, dan itu percuma. Baris keempat pula menunjukkan enjin tidak memutar id dengan sendiri, jadi tiada perlindungan automatik yang boleh diharapkan.

Kenapa cftoken tidak menyelamatkan anda?

Nasihat lama menganggap pasangan CFID dan CFTOKEN bermakna penyerang perlu meneka dua nilai. Pada rig ini andaian itu tidak lagi benar: cftoken ialah 0 pada setiap sesi yang diukur, jadi tiada entropi tambahan di situ. Sesiapa yang tahu cfid memegang sesi itu sepenuhnya, dan menyemak panjang cftoken tidak memberi perlindungan. Yang menentukan keselamatan ialah sama ada aplikasi menukar cfid apabila tahap kepercayaan berubah, iaitu pada log masuk dan pada log keluar.

Apa yang sessionRotate() lakukan kepada id dan data?

Dokumentasi Lucee menyatakan fungsi ini "invalidate current session, creates a new session and migrate the data from the old session to the new". Ujian pada rig menyokong ayat itu dengan angka. Halaman log masuk di bawah mencatat id sebelum dan selepas putaran:

<cfscript>
  // Halaman log masuk yang ringkas: semak kelayakan, putar id sesi, simpan identiti.
  penggunaId = 42;
  idSebelum = session.cfid;
  sessionRotate();
  idSelepas = session.cfid;
  session.penggunaId = penggunaId;
  session.masaLogMasuk = now();
  session.csrf = csrfGenerateToken("borang", true);
  writeOutput("sebelum: " & idSebelum & "<br>");
  writeOutput("selepas: " & idSelepas & "<br>");
  writeOutput("pengguna: " & session.penggunaId & "<br>");
  writeOutput("id berubah: " & yesNoFormat(idSebelum != idSelepas));
</cfscript>

Output sebenar daripada rig, dengan kuki bersih:

sebelum: 0e6b266b-cd07-42e0-8efb-1befadda85b5
selepas: 4852b370-88a3-49f3-98c5-bd96b7b786ba
pengguna: 42
id berubah: Yes

Tiga ukuran lain melengkapkan gambaran itu. Apabila halaman yang sama diminta dengan ?cfid=33333333-..., id sebelum putaran ialah id yang dihantar penyerang, jadi sesi memang sudah dicipta di bawah id itu dan hanya putaran yang memutuskan sambungan. Data sesi kekal selepas putaran, dan id lama membuka sesi kosong yang berasingan apabila dihantar semula.

Itu susunan yang betul untuk log masuk: sahkan kelayakan dahulu, kemudian putar, kemudian simpan identiti. Jika anda memutar sebelum kelayakan disahkan, penyerang masih boleh menetapkan id pada permintaan berikutnya. Yang tidak boleh dibuat ialah melangkaunya sama sekali.

Untuk aplikasi yang mengeluarkan token CSRF, jana token baharu dengan forceNew=true pada saat yang sama anda memutar id, kerana ujian token CSRF dalam Lucee menunjukkan token lama kekal sah selepas sessionRotate().

Bagaimana mengesan bahawa id sesi datang daripada URL?

Pengesanan ini murah dan boleh dipasang pada setiap permintaan. Jika url mengandungi cfid atau cftoken, id itu datang daripada pautan dan bukan daripada kuki yang enjin keluarkan sendiri:

<cfscript>
  // Tolak id sesi yang datang melalui URL, kerana penyerang boleh menetapkannya lebih awal.
  dariUrl = structKeyExists(url, "cfid") || structKeyExists(url, "cftoken");
  if (dariUrl) {
    sessionInvalidate();
    writeOutput("id sesi datang dari URL: sesi lama dibuang, id baharu dikeluarkan.<br>");
  } else {
    writeOutput("id sesi datang dari kuki: diterima.<br>");
  }
  session.cfidSemasa = session.cfid;
</cfscript>

Diuji pada dua permintaan. Tanpa parameter URL, halaman melaporkan id datang dari kuki. Dengan ?cfid=44444444-...&cftoken=0, halaman melaporkan id datang dari URL, dan respons membawa Set-Cookie dengan id baharu. sessionInvalidate() membuang data dan mengeluarkan id baharu, jadi sessionRotate() selepasnya tidak diperlukan.

Namun sessionInvalidate() bukan pengganti sessionRotate() pada log masuk kerana ia membuang semua data, termasuk draf borang yang mungkin hendak dikekalkan. Pada log masuk, sessionRotate() yang dipilih. Pada log keluar dan pada id yang datang daripada URL, sessionInvalidate() yang dipilih kerana data itu tidak sepatutnya dipercayai.

FungsiData sesiId sesiBila guna
sessionRotate()Dikekalkan dan dipindahkanUUID baharuSelepas kelayakan disahkan
sessionInvalidate()DibuangId baharu dikeluarkanLog keluar, id daripada URL, sesi mencurigakan

Kuki sesi: apa yang Lucee hantar dan cara mengetatkannya?

Tetapan kuki sesi diuruskan dalam Application.cfc melalui struct sessionCookie, dan dokumentasi Lucee menyenaraikan kunci httpOnly, secure, domain, timeout dan sameSite dengan nilai lax, strict atau none. Blok di bawah ialah fail Application.cfc penuh yang dijalankan pada rig:

component {
    this.name = "sesi-ketat";
    this.sessionManagement = true;
    this.sessionTimeout = createTimeSpan(0, 0, 30, 0);
    this.sessionCookie = { httpOnly: true, secure: true, sameSite: "strict" };
}

Kesan tetapan itu boleh dibaca terus daripada respons, dan begitulah cara mengesahkannya tanpa pelayar:

Set-Cookie: cfid=a9d83dae-ce8c-4d0a-8aed-eb04012c2a2c;Path=/;Expires=Sun, 29-Oct-2056 06:53:31 GMT;Secure;HttpOnly;SameSite=Strict
Set-Cookie: cftoken=0;Path=/;Expires=Sun, 29-Oct-2056 06:53:31 GMT;Secure;HttpOnly;SameSite=Strict

Tiga peringatan datang daripada ukuran yang sama. secure: true bermaksud pelayar hanya menghantar kuki itu melalui HTTPS, jadi memasangnya pada laman HTTP akan memutuskan sesi setiap pelawat. Menetapkan struct sessionCookie tanpa sameSite membuang atribut SameSite lalai, jadi nyatakan nilainya secara eksplisit. Dan timeout diukur dalam hari: "1" memberi tarikh luput sehari, manakala "0" dan "-1" kedua-duanya memberi dua puluh hari pada rig ini, bukan kuki sesi pelayar seperti yang didakwa dokumentasi.

Adakah mod sesi j2ee menyelesaikan masalah ini?

Sebahagiannya. Dalam mod j2ee, enjin menghantar JSESSIONID dan session.cfid tidak wujud. Apabila JSESSIONID yang tidak dikenali dihantar, Tomcat menolaknya dan mengeluarkan id baharu, jadi id yang ditetapkan penyerang tidak menjadi sesi. sessionRotate() pula memutar JSESSIONID dan mengekalkan data.

Namun cfid masih dihantar dalam mod j2ee. Dalam ujian, cfid daripada URL dipantulkan semula dalam Set-Cookie, tetapi data sesi tidak terkumpul di bawahnya apabila kuki JSESSIONID tiada. Sama ada aplikasi yang membaca cfid secara langsung boleh dipengaruhi dalam mod itu tidak diuji di sini, jadi uji pada aplikasi anda sendiri sebelum mengandaikan jawapannya.

Senarai semak sebelum terbit

  • Panggil sessionRotate() selepas kelayakan disahkan, sebelum menyimpan session.penggunaId.
  • Panggil sessionInvalidate() pada log keluar, dan jana semula token CSRF pada log masuk berikutnya.
  • Tolak permintaan yang membawa cfid atau cftoken dalam URL, atau buang sesi itu serta-merta.
  • Tetapkan sessionCookie dengan httpOnly, secure dan sameSite, kemudian baca Set-Cookie pada respons untuk mengesahkannya.
  • Jangan bergantung pada cftoken sebagai faktor kedua; ia 0 pada enjin ini, dan getSessionID() tidak wujud dalam Lucee 7.

Untuk simptom sesi yang hilang atau berganda, halaman sesi Lucee hilang atau berganda mengasingkan punca konfigurasi daripada punca kod. Asas penyimpanan sesi ada dalam pengurusan sesi dalam Lucee. Jika log masuk anda menggunakan kod sekali guna, lihat pengesahan pengguna dengan 2FA kerana langkah itu juga menukar tahap kepercayaan.

Soalan Lazim

Adakah session fixation mungkin dalam Lucee tanpa sebarang pepijat dalam kod saya? Ya. Enjin menerima id sesi daripada URL dan daripada kuki, dan ia tidak memutar id dengan sendiri. Aplikasi yang tidak memanggil sessionRotate() selepas log masuk terdedah walaupun kodnya betul.

Adakah cukup menukar kuki sesi selepas log masuk? Tidak. Yang perlu bertukar ialah id yang disimpan di pelayan, bukan hanya nilai dalam pelayar. sessionRotate() melakukan kedua-duanya: ia mencipta sesi baharu, memindahkan data, dan menghantar id baharu kepada klien.

Kenapa id lama masih membuka halaman selepas sessionRotate? Kerana halaman itu membuka sesi baharu yang kosong, bukan sesi lama. Dalam ujian, id lama tidak lagi memegang data yang ditulis sebelum putaran dan pembilang bermula semula.

Bolehkah saya hanya menyekat parameter cfid dalam URL melalui pemprosesan awal? Boleh, tetapi jangan jadikannya satu-satunya pertahanan. Penyerang juga boleh menetapkan id melalui kuki jika dia mengawal subdomain atau boleh menulis JavaScript pada halaman anda. Putaran pada log masuk melindungi kedua-dua laluan.

Adakah sessionRotate menamatkan sesi pengguna lain? Tidak. Ia hanya menyentuh sesi yang membuat permintaan itu. Untuk membatalkan sesi pengguna lain, contohnya selepas perubahan kata laluan, simpan id sesi bagi setiap pengguna dan batalkan secara berasingan.

Sumber

  • Dokumentasi Lucee, SessionRotate(): https://docs.lucee.org/reference/functions/sessionrotate.html
  • Dokumentasi Lucee, SessionInvalidate(): https://docs.lucee.org/reference/functions/sessioninvalidate.html
  • Dokumentasi Lucee, tag application dan struct sessionCookie: https://docs.lucee.org/reference/tags/application.html
  • OWASP, Session fixation: https://owasp.org/www-community/attacks/Session_fixation
  • OWASP, Session Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
0 komen

0 komen

Log masuk untuk menjawab atau memberi komen.

Log masuk