એક લર્નિંગ પ્લેટફોર્મ જે વિદ્યાર્થીઓને MongoDB ક્વેરીઝ લખવાની મંજૂરી આપે છે, તેણે Node.js ના vm મોડ્યુલનો ઉપયોગ કરવાનું બંધ કરી દીધું છે અને હવે તે એક્ઝિક્યુશન પહેલાં દરેક ક્વેરીને એબ્સ્ટ્રેક્ટ સિન્ટેક્સ ટ્રી (AST) માં પાર્સ કરે છે. આ ફેરફાર એ સેન્ડબોક્સને દૂર કરે છે જે તૂટી શકે તેમ હતું, જેનાથી બેકએન્ડને એવા મનસ્વી કોડથી સુરક્ષિત કરવામાં આવે છે જે કોઈ ખોટી રીતે બનાવેલી સ્ટ્રિંગ દ્વારા ઇન્જેક્ટ કરી શકાય છે.
મૂળ સેન્ડબોક્સ કેમ નિષ્ફળ ગયું
પ્રથમ અમલીકરણમાં લાઈવ ડેટાબેઝ હેન્ડલને vm.runInContext કોલમાં લપેટવામાં આવ્યું હતું અને રેગ્યુલર એક્સપ્રેશન (regular expression) દ્વારા વપરાશકર્તાઓને મર્યાદિત કરવાનો પ્રયાસ કરવામાં આવ્યો હતો. તે ફક્ત find અથવા aggregate જેવા મેથડ નામોને જ મંજૂરી આપતું હતું; અન્ય તમામ આઇડેન્ટિફાયરને ફિલ્ટર કરી દેવાના હતા.
બે ખામીઓએ તે અભિગમને અસુરક્ષિત બનાવ્યો:
- Regex ફિલ્ટરિંગને બાયપાસ કરી શકાય છે. JavaScript કોડને કોઈપણ પ્રોપર્ટી સુધી પહોંચવા માટે બ્રેકેટ નોટેશન (
obj["constructor"]) નો ઉપયોગ કરવાની મંજૂરી આપે છે. એક હુમલાખોરFunctionકન્સ્ટ્રક્ટર મેળવી શકે છે, નવું ફંક્શન બનાવી શકે છે, અને તેઓ ઈચ્છે તેવો કોઈપણ કોડ ચલાવી શકે છે. રેગ્યુલર એક્સપ્રેશન ક્યારેય મૂળ પ્રોપર્ટી એક્સેસને જોઈ શકતું નથી કારણ કે સોર્સને અસંખ્ય રીતે ફરીથી લખી શકાય છે. vmએ સુરક્ષા સીમા (security boundary) નથી. Node ના ડોક્યુમેન્ટેશન મુજબ,vmફક્ત global ઓબ્જેક્ટને અલગ કરે છે પરંતુ આખી પ્રોસેસને નહીં. સેન્ડબોક્સમાં લાઈવ ડેટાબેઝ કનેક્શન ઇન્જેક્ટ કરીને, કોન્ટેક્સ્ટની અંદરનો કોડ તે કનેક્શન પર કોઈપણ મેથડને કોલ કરવાની ક્ષમતા જાળવી રાખતો હતો, જેમાં ડેટા લખતા અથવા ડિલીટ કરતા મેથડ્સનો પણ સમાવેશ થાય છે. સેન્ડબોક્સ કોડને હોસ્ટ પ્રોસેસને અસર કરતા રોકી શક્યું નહીં.
AST-આધારિત ઉકેલ
ટીમે કોડ એક્ઝિક્યુશનને સ્ટેટિક એનાલિસિસ (static analysis) સાથે બદલી નાખ્યું છે. ક્વેરી સ્ટ્રિંગ્સ હવે acorn પાર્સરને મોકલવામાં આવે છે, જે AST બનાવે છે—જે કોડના સિન્ટેક્ટિક સ્ટ્રક્ચરનું ટ્રી રિપ્રેઝન્ટેશન છે. AST ની તપાસ કડક વ્હાઇટલિસ્ટ (whitelist) સામે નોડ-દર-નોડ કરવામાં આવે છે:
- Literals, arrays અને objects ને ફક્ત ત્યારે જ મંજૂરી આપવામાં આવે છે જ્યારે તેઓ સાદા મૂલ્યો (plain values) તરીકે દેખાય છે.
- Method calls ને અગાઉથી નિર્ધારિત સેટ (
find,sort,limit, વગેરે) સુધી મર્યાદિત રાખવામાં આવ્યા છે. અન્ય કોઈપણ કોલ રિજેક્ટ કરવામાં આવે છે. - Computed property access (દા.ત.,
obj[expr]) અથવા સ્પષ્ટપણે સૂચિબદ્ધ ન હોય તેવા કોઈપણ નોડ પ્રકારને કારણે તરત જ નિષ્ફળતા (failure) આવે છે.
કારણ કે પાર્સર કાચા ટેક્સ્ટ (raw text) પર નહીં, પણ ટ્રી પર કામ કરે છે, તેથી તેને વૈકલ્પિક સ્પેલિંગ અથવા બ્રેકેટ-નોટેશનની યુક્તિઓથી છેતરી શકાતું નથી. કન્સ્ટ્રક્ટર ચેઇન જે રેગ્યુલર એક્સપ્રેશનથી છટકી ગઈ હોત, તે અમાન્ય નોડ તરીકે દેખાય છે અને કોઈપણ કોડ ચાલતા પહેલા જ રિજેક્ટ થઈ જાય છે.
સુરક્ષા માટે આનો અર્થ શું છે
નવું ડિઝાઇન "deny by default" (ડિફોલ્ટ રીતે નકારવાની) ફિલોસોફી અનુસરે છે:
- શું મંજૂર છે તે વ્યાખ્યાયિત કરો, શું પ્રતિબંધિત છે તે નહીં. ટેક્સ્ટ્યુઅલ એલો-લિસ્ટિંગ (allow-listing) સંપૂર્ણ હોઈ શકે નહીં; AST માં નોડ પ્રકારોનો મર્યાદિત સેટ હોય છે, જે સંપૂર્ણ તપાસને વ્યવહારુ બનાવે છે.
- સેન્ડબોક્સની અંદર ક્યારેય લાઈવ રિસોર્સિસને એક્સપોઝ ન કરો. આઇસોલેટેડ કોન્ટેક્સ્ટમાં ડેટાબેઝ હેન્ડલ પસાર કરવાથી સેન્ડબોક્સ કરેલા કોડને બેકએન્ડ સુધી સીધી પહોંચ મળે છે. પાર્સર અભિગમ યુઝર કોડને ક્યારેય લાઈવ ઓબ્જેક્ટ આપતો નથી; તે ફક્ત ક્વેરીના હેતુને જ એક્સટ્રેક્ટ કરે છે.
- સ્ટ્રક્ચરને વેલિડેટ કરો, પછી સુરક્ષિત રીતે એક્ઝિક્યુટ કરો. એકવાર AST વેલિડેશન પાસ કરી લે, પછી પ્લેટફોર્મ તેના પોતાના વિશ્વસનીય કોડ પાથનો ઉપયોગ કરીને મંજૂર કરેલા કોલ્સને વાસ્તવિક MongoDB ડ્રાઇવર મેથડ્સમાં રૂપાંતરિત કરે છે.
આગળ શું ધ્યાન રાખવું
- તમારા કોડબેઝમાં
eval,new Function, અથવાvmના કોઈપણ ઉપયોગનું ઓડિટ કરો. વ્હાઇટલિસ્ટને પણ JavaScript ના ડાયનેમિક સ્વભાવ દ્વારા તોડી શકાય છે. - જ્યાં પણ શક્ય હોય ત્યાં યુઝર-જનરેટેડ કોડ માટે AST પાર્સિંગ અપનાવો.
acorn,esprima, અથવાbabel-parserજેવી લાઇબ્રેરીઓ આ રૂપાંતરણને સરળ બનાવે છે. - લાઈવ ઓબ્જેક્ટ્સના એક્સપોઝરને મર્યાદિત કરો. જો ડેટાબેઝ કનેક્શન, ફાઇલ હેન્ડલ અથવા નેટવર્ક સોકેટ સુધી પહોંચવું જરૂરી હોય, તો તેને પ્રોક્સીમાં લપેટો જે ફક્ત તમે મંજૂરી આપવા માંગતા લઘુત્તમ મેથડ્સને જ એક્સપોઝ કરે.
- એજ કેસીસ (edge cases) ના ટેસ્ટિંગને ઓટોમેટ કરો. બ્રેકેટ નોટેશન, કમ્પ્યુટેડ કીઝ અથવા પ્રોટોટાઇપ મેનિપ્યુલેશનનો ઉપયોગ કરતી ક્વેરીઝ જનરેટ કરો જેથી તમે ચકાસી શકો કે તમારું પાર્સર તેને રિજેક્ટ કરે છે.
સારાંશ
સેન્ડબોક્સ તરીકે vm.runInContext પર આધાર રાખવો એ સુરક્ષાનો ખોટો અહેસાસ આપે છે; રેગ્યુલર એક્સપ્રેશન ફિલ્ટર્સ JavaScript ના લવચીક સિન્ટેક્સને કવર કરી શકતા નથી, અને સેન્ડબોક્સ પ્રોસેસ રિસોર્સિસને અલગ પાડતું નથી. યુઝર ઇનપુટને AST માં પાર્સ કરીને અને તમે જે નોડ્સને સમજો છો તેને જ વ્હાઇટલિસ્ટ કરવાથી એક નક્કર, જાળવણી કરી શકાય તેવો અવરોધ મળે છે જે હાનિકારક કોડને ચાલતા પહેલા જ અટકાવે છે. જો તમારું પ્લેટફોર્મ વપરાશકર્તાઓને કોડ લખવાની મંજૂરી આપે છે, તો આજે જ eval-શૈલીના એક્ઝિક્યુશનને સ્ટેટિક એનાલિસિસ સાથે બદલો.
