மாணவர்களுக்கு MongoDB வினவல்களை (queries) உருவாக்க அனுமதிக்கும் ஒரு கற்றல் தளம், Node.js-ன் vm தொகுதியைப் (module) பயன்படுத்துவதை நிறுத்திவிட்டு, இப்போது ஒவ்வொரு வினவலையும் இயக்குவதற்கு முன் ஒரு அப்ஸ்ட்ராக்ட் சிந்தாக்ஸ் ட்ரீயாக (abstract syntax tree - AST) மாற்றுகிறது. இந்த மாற்றம், உடைக்கப்படக்கூடிய ஒரு சாண்ட்பாக்ஸை (sandbox) நீக்குவதன் மூலம், தவறான முறையில் உருவாக்கப்பட்ட ஒரு ஸ்ட்ரிங் (string) மூலம் ஊடுருவக்கூடிய ஏதேனும் ஒரு குறியீட்டிலிருந்து (arbitrary code) பேக்எண்டைப் பாதுகாக்கிறது.
அசல் சாண்ட்பாக்ஸ் ஏன் தோல்வியடைந்தது
முதல் முறையில், ஒரு நேரடித் தரவுத்தள ஹேண்டிலை (database handle) vm.runInContext அழைப்பிற்குள் வைத்து, ரெகுலர் எக்ஸ்பிரஷன் (regular expression) மூலம் பயனர்களைக் கட்டுப்படுத்த முயன்றது. இது find அல்லது aggregate போன்ற மெத்தட் பெயர்களை (method names) மட்டுமே அனுமதித்தது; மற்ற அனைத்து அடையாளங்களும் (identifiers) வடிகட்டப்பட வேண்டும் என்று கருதப்பட்டது.
அந்த அணுகுமுறை பாதுகாப்பற்றதாக இருப்பதற்கு இரண்டு குறைபாடுகள் காரணமாயின:
- Regex வடிகட்டுதலைத் தவிர்க்க முடியும். ஜாவாஸ்கிரிப்ட் (JavaScript) குறியீடு பிராக்கெட் நோட்டேஷனை (
obj["constructor"]) பயன்படுத்தி எந்தவொரு பண்பையும் (property) அணுக அனுமதிக்கிறது. ஒரு தாக்குதல் நடத்துபவர்Functionகன்ஸ்ட்ரக்டரை (constructor) பெற்று, ஒரு புதிய ஃபங்ஷனை உருவாக்கி, தங்களுக்குத் தேவையான எந்தக் குறியீட்டையும் இயக்க முடியும். மூலக் குறியீடு (source) எண்ணற்ற வழிகளில் மாற்றியமைக்கப்படலாம் என்பதால், அந்தப் பண்பு அணுகலை (property access) regex கண்டறியவே முடியாது. vmஎன்பது ஒரு பாதுகாப்பு எல்லை அல்ல.vmஎன்பது global ஆப்ஜெக்ட்டை மட்டுமே தனிமைப்படுத்துகிறது, முழு செயல்முறையையும் (process) அல்ல என்று Node-ன் ஆவணங்கள் கூறுகின்றன. சாண்ட்பாக்ஸிற்குள் ஒரு நேரடித் தரவுத்தள இணைப்பை (database connection) உட்புகுத்துவதன் மூலம், அந்த இணைப்பில் உள்ள தரவை எழுத அல்லது அழிக்கக்கூடிய மெத்தட்கள் உட்பட எந்தவொரு மெத்தடையும் அழைக்கும் திறனை அந்தச் சூழலுக்குள் இருக்கும் குறியீடு தக்க வைத்துக் கொள்கிறது. சாண்ட்பாக்ஸ் அந்தத் தொகுதியை (host process) பாதிப்பதைத் தடுக்கவில்லை.
AST-அடிப்படையிலான தீர்வு
குழுவினர் குறியீடு இயக்கத்திற்குப் பதிலாக ஸ்டேடிக் அனாலிசிஸை (static analysis) அறிமுகப்படுத்தினர். வினவல் ஸ்ட்ரிங்குகள் (Query strings) இப்போது acorn பார்ஸருக்கு (parser) அனுப்பப்படுகின்றன, இது குறியீட்டின் தொடரியல் அமைப்பைக் குறிக்கும் ஒரு மர வடிவிலான பிரதிநிதித்துவமான AST-ஐ உருவாக்குகிறது. இந்த AST, ஒரு கண்டிப்பான ஒயிட்லிஸ்ட்டுடன் (whitelist) நோட் வாரியாக (node-by-node) சரிபார்க்கப்படுகிறது:
- Literals, arrays மற்றும் objects ஆகியவை சாதாரண மதிப்புகளாக (plain values) இருக்கும்போது மட்டுமே அனுமதிக்கப்படுகின்றன.
- Method calls முன்கூட்டியே வரையறுக்கப்பட்ட தொகுப்பிற்கு (
find,sort,limit, போன்றவை) மட்டுமே மட்டுப்படுத்தப்பட்டுள்ளன. மற்ற எந்த அழைப்பும் நிராகரிக்கப்படும். - Computed property access (எ.கா.,
obj[expr]) அல்லது வெளிப்படையாகப் பட்டியலிடப்படாத எந்தவொரு நோட் வகையும் உடனடியாகத் தோல்வியைத் தூண்டும்.
பார்ஸர் மூல உரையைக் (raw text) கொண்டு செயல்படாமல், மர அமைப்பைக் (tree) கொண்டு செயல்படுவதால், மாற்று எழுத்து முறைகளாலோ அல்லது பிராக்கெட் நோட்டேஷன் தந்திரங்களாலோ அதை ஏமாற்ற முடியாது. regex-ஐத் தாண்டிச் சென்றிருக்கக்கூடிய ஒரு கன்ஸ்ட்ரக்டர் செயின் (constructor chain), அடையாளம் காணப்படாத நோடாகத் தோன்றும் மற்றும் எந்தக் குறியீடும் இயங்குவதற்கு முன்பே நிராகரிக்கப்படும்.
இது பாதுகாப்பிற்கு எதைக் குறிக்கிறது
புதிய வடிவமைப்பு "deny by default" (இயல்பாகவே மறுத்தல்) தத்துவத்தைப் பின்பற்றுகிறது:
- தடைசெய்யப்பட்டதை அல்ல, அனுமதிக்கப்பட்டதை வரையறுக்கவும். உரை அடிப்படையிலான அனுமதிப் பட்டியல் (allow-listing) முழுமையானதாக இருக்க முடியாது; ஆனால் AST ஒரு குறிப்பிட்ட எண்ணிக்கையிலான நோட் வகைகளைக் கொண்டிருப்பதால், முழுமையான சரிபார்ப்பு சாத்தியமாகிறது.
- சாண்ட்பாக்ஸிற்குள் நேரடி வளங்களை (live resources) ஒருபோதும் வெளிப்படுத்த வேண்டாம். ஒரு தனிமைப்படுத்தப்பட்ட சூழலுக்குத் தரவுத்தள ஹேண்டிலை அனுப்புவது, சாண்ட்பாக்ஸ் குறியீட்டிற்கு பேக்எண்டிற்குச் செல்ல ஒரு நேரடி வழியைத் தருகிறது. பார்ஸர் அணுகுமுறை பயனர் குறியீட்டிற்கு ஒரு நேரடி ஆப்ஜெக்ட்டையும் வழங்குவதில்லை; அது வினவலின் நோக்கத்தை (intent) மட்டுமே பிரித்தெடுக்கிறது.
- அமைப்பைச் சரிபார்க்கவும், பின்னர் பாதுகாப்பாக இயக்கவும். AST சரிபார்ப்பைத் தாண்டியதும், தளம் தனது சொந்த நம்பகமான குறியீடு பாதையைப் பயன்படுத்தி, அனுமதிக்கப்பட்ட அழைப்புகளை உண்மையான MongoDB டிரைவர் மெத்தட்களாக மாற்றுகிறது.
அடுத்து கவனிக்க வேண்டியவை
- உங்கள் கோட்பாட்டில் (codebase)
eval,new Function, அல்லதுvm-ன் பயன்பாடுகளைத் தணிக்கை (audit) செய்யுங்கள். ஒரு ஒயிட்லிஸ்ட் கூட ஜாவாஸ்கிரிப்ட்டின் மாறும் தன்மையால் (dynamic nature) முறியடிக்கப்படலாம். - முடிந்தவரை பயனர் உருவாக்கும் குறியீட்டிற்கு AST பார்சிங் முறையைப் பின்பற்றுங்கள்.
acorn,esprima, அல்லதுbabel-parserபோன்ற லைப்ரரிகள் இந்த மாற்றத்தை எளிதாக்குகின்றன. - நேரடி ஆப்ஜெக்ட்களின் வெளிப்பாட்டைக் கட்டுப்படுத்துங்கள். ஒரு தரவுத்தள இணைப்பு, ஃபைல் ஹேண்டல் அல்லது நெட்வொர்க் சாக்கெட் (network socket) அணுகப்பட வேண்டியிருந்தால், நீங்கள் அனுமதிக்க விரும்பும் குறைந்தபட்ச மெத்தட்களை மட்டுமே வெளிப்படுத்தும் ஒரு ப்ராக்ஸியில் (proxy) அதைச் சுற்றவும்.
- எட்ஜ் கேஸ்களை (edge cases) தானியக்கமாக்கிச் சோதிக்கவும். உங்கள் பார்ஸர் அவற்றை நிராகரிக்கிறதா என்பதைச் சரிபார்க்க, பிராக்கெட் நோட்டேஷன், கம்ப்யூட்டட் கீகள் (computed keys) அல்லது புரோட்டோடைப் கையாளுதல் (prototype manipulation) ஆகியவற்றைப் பயன்படுத்தும் வினவல்களை உருவாக்கவும்.
சுருக்கம்
vm.runInContext-ஐ ஒரு சாண்ட்பாக்ஸாக நம்புவது ஒரு தவறான பாதுகாப்பு உணர்வைத் தருகிறது; regex வடிகட்டிகளால் ஜாவாஸ்கிரிப்ட்டின் நெகிழ்வான தொடரியலை (syntax) முழுமையாகக் கையாள முடியாது, மேலும் சாண்ட்பாக்ஸ் செயல்முறை வளங்களைத் (process resources) தனிமைப்படுத்துவதும் இல்லை. பயனர் உள்ளீட்டை ஒரு AST-ஆக மாற்றி, நீங்கள் புரிந்துகொள்ளும் நோட்களை மட்டும் ஒயிட்லிஸ்ட் செய்வது, தீய குறியீடு இயங்குவதற்கு முன்பே அதைத் தடுக்கும் ஒரு உறுதியான மற்றும் பராமரிக்கக்கூடிய தடையை வழங்குகிறது. உங்கள் தளம் பயனர்களைக் குறியீடு எழுத அனுமதிக்கிறது என்றால், eval-பாணி இயக்கத்திற்குப் பதிலாக இன்றே ஸ்டேடிக் அனாலிசிஸைப் பயன்படுத்துங்கள்.
