எனது சொந்த authentication layer-ஐ உருவாக்குவது ஒரு பெருமைக்குரிய விஷயம் என்று நான் முன்பு நினைத்தேன். உங்களுக்கு JWTs பற்றித் தெரிந்தும், ஒரு password-ஐ hash செய்யத் தெரிந்தும், இதில் என்ன கடினம் என்று கேட்டால்? நான் ஒரு Node backend-ஐ உருவாக்கி, tokens-களை வழங்கினேன், அவ்வளவுதான் என்று நினைத்தேன். அந்த code வேலை செய்தது. Tests அனைத்தும் வெற்றியடைந்தன. பின்னர், உண்மையான தாக்குதல்கள் (attacks) எவ்வாறு நிகழ்கின்றன என்பதைப் பற்றிப் படிக்கத் தொடங்கியபோது, நான் அதிர்ச்சியடைந்தேன். Injection, enumeration மற்றும் side-channel leaks பற்றிய ஒவ்வொரு அத்தியாயமும் என்னை ஒருவித பயத்துடன் மீண்டும் எனது editor-இடம் அழைத்துச் சென்றது. எனது auth system-இல் வெறும் இடைவெளிகள் மட்டும் இல்லை; நானே அமைத்த நான்கு பெரிய கதவுகள் திறந்தே இருந்தன. நான் கண்டறிந்தவை மற்றும் நான் மாற்றியவை இதோ.

String Concatenation மூலம் ஏற்படும் SQL Injection

முதல் பிழை மிகவும் பழமையான ஒரு தந்திரமாகும். நான் பயனர் உள்ளீட்டை (user input) நேரடியாக SQL strings-க்குள் சேர்த்துக் கொண்டிருந்தேன். எனது login route-இல், request body-யிலிருந்து email-ஐ எடுத்து, அதை SELECT * FROM users WHERE email = '${email}' போன்ற ஒரு query-இல் இணைத்தேன். frontend-ஐ நான் கட்டுப்படுத்துவதால் இது பாதுகாப்பானது என்று தோன்றியது. அது ஒரு ஆபத்தான அனுமானம். ஒரு தாக்குதலுக்கு (attacker) உங்கள் frontend தேவையில்லை. ஒரு முறையான POST body மூலம் அந்த login check-ஐ ஒரு தரவு கசிவாகவோ (data breach) அல்லது தரவுத்தளம் முழுமையாக அழிக்கப்படுவதற்கோ மாற்ற முடியும். ' OR '1'='1 போன்ற ஒரு payload-ஐ அல்லது இன்னும் மோசமாக, tables-களை அழிக்கும் ஒரு stacked query-ஐ அனுப்பினால், அந்த string அப்படியே இயக்கப்பட்டால், உங்கள் தரவு காணாமல் போய்விடும். எனது code மற்றும் தாக்குதலாளியின் தரவு (attacker's data) ஆகியவற்றுக்கு இடையே வேறுபாட்டைத் தீர்மானிக்கத் தரவுத்தளத்திற்கு (database) எந்த வழியையும் நான் வழங்கவில்லை.

இதற்கான தீர்வு கூடுதல் input validation அல்லது strings-களைக் கையால் escaping செய்வது அல்ல. உண்மையான தீர்வு parameterized queries ஆகும். நான் node-postgres-க்கு மாறினேன் மற்றும் $1 போன்ற placeholders-களைப் பயன்படுத்தத் தொடங்கினேன். இப்போது query ஒரு template போல மாறும்: SELECT * FROM users WHERE email = $1. driver, SQL மற்றும் மதிப்புகளை (values) தனித்தனி வழிகள் மூலம் அனுப்புகிறது. அந்த உள்ளீட்டில் என்ன எழுத்துக்கள் இருந்தாலும், database அதைத் தரவாக மட்டுமே கருதும். இந்த ஒரு மாற்றம் injection attacks வகையிலான அனைத்துத் தாக்குதல்களையும் தடுத்துவிடும். இது வாசிப்பதற்கு எளிதானது, பராமரிக்க எளிதானது, மேலும் ஒவ்வொரு முறையும் நீங்கள் WHERE clause எழுதும்போது ஒரு regex wizard ஆக இருக்க வேண்டிய அவசியத்தையும் இது நீக்குகிறது.

Error Messages மூலம் மின்னஞ்சல் விவரங்களைச் சேகரித்தல் (Email Enumeration)

எனது இரண்டாவது தவறு சிறந்த UX போலத் தெரிந்தது. ஒரு பயனர் தவறான email-ஐத் தட்டச்சு செய்யும்போது, நான் User not found என்று பதிலளித்தேன். அவர்கள் சரியான email-ஐக் கொடுத்துவிட்டு தவறான password-ஐப் பயன்படுத்தினால், Incorrect password என்று பதிலளித்தேன். இது பயனுள்ளதாகத் தோன்றியது. ஆனால், இது தாக்குதலாளிகளுக்கான ஒரு reconnaissance tool ஆகவும் இருந்தது. Enumeration scripts ஆயிரக்கணக்கான மின்னஞ்சல் முகவரிகளுடன் உங்கள் login endpoint-ஐத் தாக்க முடியும். கணக்கு இருக்கிறதா இல்லையா என்பதைப் பொறுத்து response body அல்லது status code மாறினால், அந்த script உங்கள் பயனர்களின் சரிபார்க்கப்பட்ட பட்டியலை உருவாக்க முடியும். அந்தப் பட்டியல் credential stuffing, targeted phishing மற்றும் மேலும் brute-force முயற்சிகளுக்கான அடிப்படையாக அமைகிறது.

பயனர் எளிமைக்காக (user-friendliness) சில நேரங்களில் பாதுகாப்பைத் (security) தியாகம் செய்ய வேண்டியிருக்கும் என்பதை நான் ஏற்றுக்கொள்ள வேண்டியிருந்தது. தோல்வியடைந்த ஒவ்வொரு login path-யும் ஒரே மாதிரியான செய்தியைத் தரும்படி மாற்றினேன்: Invalid credentials. எந்தத் தகவலும் இல்லை. error response-இல் எந்தப் பிரிவினையும் (branching logic) இல்லை. மின்னஞ்சல் இல்லாவிட்டாலும், password தவறாக இருந்தாலும் அல்லது கணக்கு முடக்கப்பட்டிருந்தாலும், அந்தத் தகவல் அப்படியே இருக்கும். இது registration மற்றும் password-reset flows-களுக்கும் பொருந்தும்; ஒரு மின்னஞ்சல் முகவரி ஏற்கனவே உங்கள் அமைப்பில் உள்ளதா என்பதை வெளிப்படுத்த வேண்டாம். ஒரு பொதுவான செய்தி (generic message), தாக்குதலாளிகள் நம்பியிருக்கும் தகவல் கசிவை (information leak) நீக்குகிறது.

Password Comparison-இல் Timing Attacks

மூன்றாவது பிழை கண்ணுக்குத் தெரியாதது. நான்