கையொப்பமிடப்பட்ட (Signed) URL-களைப் பாதிக்கும் ட்ராக்கிங்-லிங்க் பிழை

மிக முக்கியமான விஷயங்களை மட்டுமே பாதிக்கும்போது ஒரு பிழை (bug) ஆபத்தானதாக மாறக்கூடும்.

mail-history-இல் நான் ஒரு பிழையைக் கண்டறிந்தேன்; இது சாதாரண லிங்க்குகளுக்குச் சரியாக வேலை செய்கிறது, ஆனால் Signed URLs-களில் தோல்வியடைகிறது. இது மின்னஞ்சல் சரிபார்ப்பு லிங்க்குகள் (email verification links) மற்றும் கையொப்பமிடப்பட்ட டவுன்லோட் லிங்க்குகளைப் பாதிக்கிறது. இந்த லிங்க்குகளில் ஒரு தவறான எழுத்து இருந்தால் கூட, Laravel அந்த கோரிக்கையை (request) நிராகரித்துவிடும்.

இது எப்படி நடந்தது என்பதை இங்கே காணலாம்.

mail-history உங்கள் HTML-ஐ மாற்றி எழுதுவதன் மூலம் மின்னஞ்சல் கிளிக்குகளைக் கண்காணிக்கிறது. இது ஒவ்வொரு லிங்க்கையும் முதலில் ஒரு redirect endpoint வழியாகச் செல்லும் வகையில் மாற்றுகிறது. இந்த endpoint கிளிக்கைப் பதிவு செய்துவிட்டு, பின்னர் பயனரை உண்மையான இடத்திற்கு அனுப்புகிறது.

இதைச் செய்ய, சிஸ்டம் அசல் URL-ஐ ஒரு ட்ராக்கிங் லிங்க்காக என்க்ரிப்ட் (encrypt) செய்கிறது.

சிஸ்டம் ரெண்டர் செய்யப்பட்ட (rendered) HTML-லிருந்து URL-ஐ எடுக்கும்போது பிரச்சனை தொடங்குகிறது. கோட் (code) மின்னஞ்சல் உள்ளடக்கத்தைப் படிக்கும்போது, Laravel ஏற்கனவே HTML-ஐ எஸ்கேப் (escape) செய்துவிடுகிறது. ஒரு லிங்க்கில் உள்ள ampersand (&) என்பது & ஆக மாறிவிடுகிறது.

https://example.com/page போன்ற ஒரு சாதாரண லிங்க் நன்றாக வேலை செய்யும். அதில் ampersands இல்லை.

ஆனால் ஒரு Signed URL இப்படி இருக்கும்: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef

HTML-இல், அது இப்படி மாறும்: https://example.com/email/verify/1/abc?expires=123&signature=deadbeef

கோட் அந்த & சரத்தை (string) என்க்ரிப்ட் செய்கிறது. பயனர் கிளிக் செய்யும்போது, சிஸ்டம் அதை டீக்ரிப்ட் (decrypt) செய்து, & கொண்ட ஒரு URL-க்கு பயனரை அனுப்புகிறது. Laravel கையொப்பத்தைச் சரிபார்க்க முயல்கிறது, ஆனால் எழுத்துக்கள் அசல் URL-உடன் பொருந்தாததால் கையொப்பச் சரிபார்ப்பு தோல்வியடைகிறது.

இதற்கான தீர்வு ஒரே ஒரு வரி கோட் மட்டுமே. URL-ஐ என்க்ரிப்ட் செய்வதற்கு முன், நீங்கள் HTML entities-களை டீகோட் (decode) செய்ய வேண்டும்.

$originalUrl = html_entity_decode($matches[2], ENT_QUOTES | ENT_HTML5);

இது என்க்ரிப்ஷன் நடப்பதற்கு முன்பே &-ஐ மீண்டும் & ஆக மாற்றுகிறது. இப்போது டீக்ரிப்ட் செய்யப்பட்ட லிங்க், அசல் Signed URL-உடன் பைட் வாரியாக (byte for byte) சரியாகப் பொருந்துகிறது.

இது மீண்டும் நடக்காமல் இருக்க நான் ஒரு டெஸ்டையும் (test) சேர்த்துள்ளேன். டீக்ரிப்ட் செய்யப்பட்ட URL-இல் & என்பதற்குப் பதிலாக உண்மையான & உள்ளதா என்பதை இந்த டெஸ்ட் சரிபார்க்கிறது.

இது போன்ற சிறிய திருத்தங்கள் எதிர்கால கோட் கிளீன்அப்களின் (code cleanups) போது எளிதில் விடுபட்டுவிடக்கூடும். எனவே, குறிப்பிட்ட தோல்வியைக் குறிப்பிடும் வகையில் எப்போதும் ஒரு டெஸ்டை எழுதுங்கள்.

உங்களுக்கான பாடங்கள்:

  • ரெண்டர் செய்யப்பட்ட HTML-லிருந்து தரவை எடுக்கிறீர்கள் என்றால், அது எஸ்கேப் செய்யப்பட்டிருக்கலாம் என்று கருதுங்கள்.
  • பிரவுசர் (browser) எஸ்கேப் செய்யப்பட்ட எழுத்துக்களை உங்களுக்காகச் சரிசெய்துவிடும். ஆனால் என்க்ரிப்ஷன் மற்றும் ரீடைரக்ட்ஸ் (redirects) அவ்வாறு செய்யாது.
  • ஒரு வரி திருத்தங்களைப் பாதுகாக்க டெஸ்ட்களைப் பயன்படுத்துங்கள்.

ஆதாரம்: https://dev.to/nasrulhazim/the-tracking-link-bug-that-only-breaks-signed-urls-38c