Bug Tautan Pelacakan yang Merusak Signed URL
Sebuah bug bisa menjadi berbahaya jika ia hanya merusak hal-hal yang paling penting.
Saya menemukan bug di mail-history yang bekerja dengan sempurna untuk tautan normal tetapi gagal untuk signed URL. Bug ini merusak tautan verifikasi email dan tautan unduhan bertanda (signed download links). Ini adalah jenis tautan di mana satu karakter yang salah saja akan menyebabkan Laravel menolak permintaan tersebut.
Begini cara hal itu terjadi.
mail-history melacak klik email dengan menulis ulang HTML Anda. Ia mengubah setiap tautan agar melewati endpoint pengalihan (redirect endpoint) terlebih dahulu. Endpoint ini mencatat klik tersebut dan kemudian mengarahkan pengguna ke tujuan yang sebenarnya.
Untuk melakukan ini, sistem mengenkripsi URL asli menjadi tautan pelacakan.
Masalah dimulai saat sistem mengambil URL dari HTML yang telah dirender. Pada saat kode membaca isi email, Laravel sudah melakukan escaping pada HTML tersebut. Karakter ampersand (&) dalam sebuah tautan berubah menjadi &.
Tautan normal seperti https://example.com/page berjalan lancar. Tautan tersebut tidak memiliki ampersand.
Namun, signed URL terlihat seperti ini: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef
Di dalam HTML, ia menjadi: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef
Kode tersebut mengenkripsi string & tersebut. Saat pengguna mengklik, sistem mendekripsinya dan mengarahkan mereka ke URL yang mengandung &. Laravel mencoba memverifikasi tanda tangan (signature), tetapi verifikasi gagal karena karakternya tidak cocok dengan yang asli.
Perbaikannya hanya berupa satu baris kode. Anda harus mendekode entitas HTML sebelum mengenkripsi URL tersebut.
$originalUrl = html_entity_decode($matches[2], ENT_QUOTES | ENT_HTML5);
Ini mengubah & kembali menjadi & sebelum enkripsi dilakukan. Tautan yang didekripsi sekarang cocok dengan signed URL asli secara byte demi byte.
Saya juga menambahkan sebuah pengujian (test) untuk mencegah hal ini terjadi lagi. Pengujian tersebut memastikan bahwa URL yang didekripsi berisi & yang asli dan bukan &.
Perbaikan kecil seperti ini mudah hilang saat pembersihan kode (code cleanup) di masa mendatang. Selalu tulis pengujian yang menyebutkan kegagalan spesifiknya.
Pelajaran untuk Anda:
- Jika Anda mengekstrak data dari HTML yang telah dirender, asumsikan data tersebut sudah di-escape.
- Browser akan memperbaiki karakter yang di-escape untuk Anda. Enkripsi dan pengalihan tidak akan melakukannya.
- Gunakan pengujian untuk melindungi perbaikan satu baris kode.
Sumber: https://dev.to/nasrulhazim/the-tracking-link-bug-that-only-breaks-signed-urls-38c
