"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > अविश्वसनीय जावास्क्रिप्ट कोड चल रहा है

अविश्वसनीय जावास्क्रिप्ट कोड चल रहा है

2024-07-29 को प्रकाशित
ब्राउज़ करें:802

Running Untrusted JavaScript Code

महत्वपूर्ण: यह केवल जावास्क्रिप्ट और टाइपस्क्रिप्ट कोड चलाने के बारे में है। ऐसा कहा जा रहा है कि, लेखन अन्य भाषाओं में अन्य कोड चलाने की दिशा भी हो सकता है।

उपयोगकर्ताओं को आपके एप्लिकेशन के भीतर अपना कोड निष्पादित करने की अनुमति देने से अनुकूलन और कार्यक्षमता की दुनिया खुल जाती है, फिर भी यह आपके प्लेटफ़ॉर्म को महत्वपूर्ण सुरक्षा खतरों के प्रति भी उजागर करता है।

यह देखते हुए कि यह उपयोगकर्ता कोड है, सर्वर को रोकने (यह अनंत लूप हो सकता है) से लेकर संवेदनशील जानकारी चुराने तक सब कुछ अपेक्षित है।

यह आलेख रन उपयोगकर्ता कोड को कम करने के लिए विभिन्न रणनीतियों का पता लगाएगा, जिसमें वेब वर्कर्स, स्थिर कोड विश्लेषण और बहुत कुछ शामिल है...

आपको परवाह करनी चाहिए

ऐसे कई परिदृश्य हैं जहां आपको उपयोगकर्ता द्वारा प्रदत्त कोड को चलाने की आवश्यकता होती है, जिसमें कोडसैंडबॉक्स और स्टैकबिल्ट्ज़ जैसे सहयोगी विकास वातावरण से लेकर जनवरी जैसे अनुकूलन योग्य एपीआई प्लेटफ़ॉर्म तक शामिल हैं। यहां तक ​​कि कोड खेल के मैदान भी जोखिम के प्रति संवेदनशील होते हैं।

अर्थात्, उपयोगकर्ता द्वारा प्रदत्त कोड को सुरक्षित रूप से चलाने के दो आवश्यक लाभ हैं:

  1. अपने उपयोगकर्ता का विश्वास हासिल करना: भले ही उपयोगकर्ता भरोसेमंद हो, वे अन्य जानबूझकर बुरे लोगों से कॉपी किए गए कोड को निष्पादित कर सकते हैं।
  2. अपने वातावरण को सुरक्षित करें: आखिरी चीज जो आपको चाहिए वह है आपके सर्वर को रोकने वाला कोड का एक टुकड़ा। सोचो जबकि (सत्य) {}

"संवेदनशील जानकारी" को परिभाषित करें

उपयोगकर्ता कोड चलाना तब तक हानिकारक नहीं है जब तक आप चिंतित न हों कि इससे कुछ डेटा चोरी हो सकता है। आप जिस भी डेटा को लेकर चिंतित हैं उसे संवेदनशील जानकारी माना जाएगा। उदाहरण के लिए, ज्यादातर मामलों में, JWT संवेदनशील जानकारी है (शायद जब प्रमाणीकरण तंत्र के रूप में उपयोग किया जाता है)

क्या गलत जा सकता है

प्रत्येक अनुरोध के साथ भेजी गई कुकीज़ में संग्रहीत JWT के संभावित जोखिमों पर विचार करें। एक उपयोगकर्ता अनजाने में एक अनुरोध ट्रिगर कर सकता है जो JWT को एक दुर्भावनापूर्ण सर्वर पर भेजता है, और...

  • क्रॉस-साइट स्क्रिप्टिंग (XSS).
  • सेवा से इनकार (DoS) हमले।
  • डेटा एक्सफिल्ट्रेशन। उचित सुरक्षा उपायों के बिना, ये खतरे आपके एप्लिकेशन की अखंडता और प्रदर्शन से समझौता कर सकते हैं।

तरीकों

द एविल इवल

सबसे सरल, फिर भी सबसे जोखिम भरा।

eval('console.log("I am dangerous!")');

जब आप यह कोड चलाते हैं, तो यह उस संदेश को लॉग करता है। मूलतः, eval एक JS दुभाषिया है जो वैश्विक/विंडो दायरे तक पहुँचने में सक्षम है।

const res = await eval('fetch(`https://jsonplaceholder.typicode.com/users`)');
const users = await res.json();

यह कोड फ़ेच का उपयोग करता है जिसे वैश्विक दायरे में परिभाषित किया गया है। दुभाषिया को इसके बारे में पता नहीं है, लेकिन चूंकि eval एक विंडो तक पहुंच सकता है, इसलिए उसे पता है। इसका तात्पर्य यह है कि ब्राउज़र में eval चलाना सर्वर वातावरण या वर्कर में चलाने से अलग है।

eval(`document.body`);

इस बारे में कैसा है...

eval(`while (true) {}`);

यह कोड ब्राउज़र टैब को रोक देगा। आप पूछ सकते हैं कि कोई उपयोगकर्ता स्वयं के साथ ऐसा क्यों करेगा। खैर, हो सकता है कि वे इंटरनेट से कोड कॉपी कर रहे हों। इसीलिए निष्पादन के साथ/या टाइम-बॉक्स के साथ स्थैतिक विश्लेषण करना पसंद किया जाता है।

आप eval के बारे में एमडीएन डॉक्स की जांच करना चाह सकते हैं

टाइम बॉक्स निष्पादन वेब वर्कर में कोड चलाकर और निष्पादन समय को सीमित करने के लिए सेटटाइमआउट का उपयोग करके किया जा सकता है।

async function timebox(code, timeout = 5000) {
  const worker = new Worker('user-runner-worker.js');
  worker.postMessage(code);

  const timerId = setTimeout(() => {
    worker.terminate();
    reject(new Error('Code execution timed out'));
  }, timeout);

  return new Promise((resolve, reject) => {
    worker.onmessage = event => {
      clearTimeout(timerId);
      resolve(event.data);
    };
    worker.onerror = error => {
      clearTimeout(timerId);
      reject(error);
    };
  });
}

await timebox('while (true) {}');

फ़ंक्शन कंस्ट्रक्टर

यह eval के समान है लेकिन यह थोड़ा अधिक सुरक्षित है क्योंकि यह संलग्न दायरे तक नहीं पहुंच सकता है।

const userFunction = new Function('param', 'console.log(param);');
userFunction(2);

यह कोड 2 लॉग करेगा।

नोट: दूसरा तर्क फ़ंक्शन बॉडी है।

फ़ंक्शन कंस्ट्रक्टर संलग्न दायरे तक नहीं पहुंच सकता है, इसलिए निम्नलिखित कोड एक त्रुटि देगा।

function fnConstructorCannotUseMyScope() {
  let localVar = 'local value';
  const userFunction = new Function('return localVar');
  return userFunction();
}

लेकिन यह वैश्विक दायरे तक पहुंच सकता है इसलिए उपरोक्त उदाहरण काम करता है।

वेबवर्कर

आप वेबवर्कर पर "फ़ंक्शन कंस्ट्रक्टर और इवल" चला सकते हैं, जो इस तथ्य के कारण थोड़ा सुरक्षित है कि कोई DOM एक्सेस नहीं है।

अधिक प्रतिबंध लगाने के लिए, वैश्विक वस्तुओं जैसे फ़ेच, XMLHttpRequest, sentBeacon का उपयोग करने की अनुमति न देने पर विचार करें। आप यह कैसे कर सकते हैं, इसके बारे में इस लेख को देखें।

पृथक-वीएम

आइसोलेटेड-वीएम एक लाइब्रेरी है जो आपको एक अलग वीएम (v8 के आइसोलेट इंटरफ़ेस) में कोड चलाने की अनुमति देती है

import ivm from 'isolated-vm';

const code = `count  = 5;`;

const isolate = new ivm.Isolate({ memoryLimit: 32 /* MB */ });
const script = isolate.compileScriptSync(code);
const context = isolate.createContextSync();

const jail = context.global;
jail.setSync('log', console.log);

context.evalSync('log("hello world")');

यह कोड हैलो वर्ल्ड लॉग करेगा

वेबअसेंबली

यह एक रोमांचक विकल्प है क्योंकि यह कोड चलाने के लिए सैंडबॉक्स वाला वातावरण प्रदान करता है। एक चेतावनी यह है कि आपको जावास्क्रिप्ट बाइंडिंग वाले वातावरण की आवश्यकता है। हालाँकि, एक्स्टिज़्म नामक एक दिलचस्प परियोजना इसे सुविधाजनक बनाती है। आप शायद उनके ट्यूटोरियल का अनुसरण करना चाहेंगे।

इसके बारे में दिलचस्प बात यह है कि आप कोड को चलाने के लिए eval का उपयोग करेंगे, लेकिन WebAssembly की प्रकृति को देखते हुए, DOM, नेटवर्क, फ़ाइल सिस्टम और होस्ट वातावरण तक पहुंच संभव नहीं है (हालाँकि वे इसके आधार पर भिन्न हो सकते हैं) wasm रनटाइम).

function evaluate() {
  const { code, input } = JSON.parse(Host.inputString());
  const func = eval(code);
  const result = func(input).toString();
  Host.outputString(result);
}

module.exports = { evaluate };

आपको पहले Extism का उपयोग करके उपरोक्त कोड को संकलित करना होगा, जो एक Wasm फ़ाइल को आउटपुट करेगा जिसे एक ऐसे वातावरण में चलाया जा सकता है जिसमें Wasm-रनटाइम (ब्राउज़र या नोड.js) है।

const message = {
  input: '1,2,3,4,5',
  code: `
        const sum = (str) => str
          .split(',')
          .reduce((acc, curr) => acc   parseInt(curr), 0);
        module.exports = sum;
`,
};

// continue running the wasm file

डाक में काम करनेवाला मज़दूर

अब हम सर्वर-साइड पर जा रहे हैं, होस्ट मशीन से अलग कोड चलाने के लिए डॉकर एक बढ़िया विकल्प है। (कंटेनर भागने से सावधान रहें)

आप कंटेनर में कोड चलाने के लिए डॉकरोड का उपयोग कर सकते हैं।

import Docker from 'dockerode';
const docker = new Docker();

const code = `console.log("hello world")`;
const container = await docker.createContainer({
  Image: 'node:lts',
  Cmd: ['node', '-e', code],
  User: 'node',
  WorkingDir: '/app',
  AttachStdout: true,
  AttachStderr: true,
  OpenStdin: false,
  AttachStdin: false,
  Tty: true,
  NetworkDisabled: true,
  HostConfig: {
    AutoRemove: true,
    ReadonlyPaths: ['/'],
    ReadonlyRootfs: true,
    CapDrop: ['ALL'],
    Memory: 8 * 1024 * 1024,
    SecurityOpt: ['no-new-privileges'],
  },
});

ध्यान रखें कि आपको यह सुनिश्चित करना होगा कि सर्वर पर डॉकर स्थापित और चालू है। मैं केवल इसके लिए समर्पित एक अलग सर्वर रखने की अनुशंसा करूंगा जो एक शुद्ध-फ़ंक्शन सर्वर के रूप में कार्य करता है।

इसके अलावा, आपको sysbox पर एक नज़र डालने से लाभ हो सकता है, एक VM-जैसा कंटेनर रनटाइम जो अधिक सुरक्षित वातावरण प्रदान करता है। Sysbox इसके लायक है, खासकर यदि मुख्य ऐप एक कंटेनर में चल रहा है, जिसका अर्थ है कि आप Docker को Docker में चला रहे होंगे।

जनवरी में यह पसंद का तरीका था लेकिन जल्द ही, भाषा क्षमताओं ने कंटेनर शेल के माध्यम से कोड को पारित करने से अधिक अनिवार्य कर दिया। इसके अलावा, किसी कारण से, सर्वर मेमोरी बार-बार बढ़ती है; हम प्रत्येक 1s डिबाउंस कीस्ट्रोक पर स्व-हटाने योग्य कंटेनरों के अंदर कोड चलाते हैं। (आप बेहतर कर सकते हैं!)

अन्य विकल्प

  • वेब कंटेनर
  • माइक्रोवीएम (पटाखा)
  • डेनो सबहोस्टिंग
  • वासमर
  • छाया क्षेत्र

सबसे सुरक्षित विकल्प

मैं विशेष रूप से फायरक्रैकर का शौकीन हूं, लेकिन इसे स्थापित करने में थोड़ा काम लगता है, इसलिए यदि आप अभी तक समय नहीं दे सकते हैं, तो आप सुरक्षित रहना चाहते हैं, स्थैतिक विश्लेषण और टाइम-बॉक्सिंग निष्पादन का संयोजन करें . आप कोड को पार्स करने और किसी दुर्भावनापूर्ण कृत्य की जांच करने के लिए एस्प्रिमा का उपयोग कर सकते हैं।

टाइपस्क्रिप्ट कोड कैसे चलाएँ?

खैर, एक (वैकल्पिक हो सकता है) अतिरिक्त चरण के साथ भी यही कहानी है: कोड को चलाने से पहले उसे जावास्क्रिप्ट में ट्रांसपाइल करें। सीधे शब्दों में कहें तो, आप esbuild या टाइपस्क्रिप्ट कंपाइलर का उपयोग कर सकते हैं, फिर उपरोक्त विधियों को जारी रख सकते हैं।

async function build(userCode: string) {
  const result = await esbuild.build({
    stdin: {
      contents: `${userCode}`,
      loader: 'ts',
      resolveDir: __dirname,
    },
    inject: [
      // In case you want to inject some code
    ],
    platform: 'node',
    write: false,
    treeShaking: false,
    sourcemap: false,
    minify: false,
    drop: ['debugger', 'console'],
    keepNames: true,
    format: 'cjs',
    bundle: true,
    target: 'es2022',
    plugins: [
      nodeExternalsPlugin(), // make all the non-native modules external
    ],
  });
  return result.outputFiles![0].text;
}

टिप्पणियाँ:

  • रस्ट-आधारित बंडलर आमतौर पर एक वेब असेंबली संस्करण पेश करते हैं, जिसका अर्थ है कि आप ब्राउज़र में कोड ट्रांसपाइल कर सकते हैं। Esbuild का एक वेब असेंबली संस्करण है।
  • उपयोगकर्ता निर्दिष्ट आयात को बंडल में तब तक शामिल न करें जब तक कि आपने उन्हें अनुमति-सूचीबद्ध न कर दिया हो।

इसके अतिरिक्त, आप डॉकर कंटेनर में Deno या Bun का उपयोग करके कोड चलाकर पूरी तरह से ट्रांसपिलिंग से बच सकते हैं क्योंकि वे बॉक्स से बाहर टाइपस्क्रिप्ट का समर्थन करते हैं।

निष्कर्ष

उपयोगकर्ता कोड चलाना एक दोधारी तलवार है। यह आपके प्लेटफ़ॉर्म पर बहुत सारी कार्यक्षमता और अनुकूलन प्रदान कर सकता है, लेकिन यह आपको महत्वपूर्ण सुरक्षा जोखिमों से भी अवगत कराता है। जोखिमों को समझना और उन्हें कम करने के लिए उचित उपाय करना आवश्यक है और याद रखें कि पर्यावरण जितना अधिक पृथक होगा, उतना ही सुरक्षित होगा।

संदर्भ

  • जनवरी तत्काल संकलन
  • Node.js में अविश्वसनीय जावास्क्रिप्ट चला रहा है
  • भाषाएँ रनटाइम पर अविश्वसनीय उपयोगकर्ता कोड को निष्पादित करने का समर्थन कैसे करती हैं?
  • संदर्भ डेटा के साथ जावास्क्रिप्ट का सुरक्षित मूल्यांकन
विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/this-is-learning/running-untrusted-javascript-code-3mi3?1 यदि कोई उल्लंघन है, तो कृपया इसे हटाने के लिए [email protected] से संपर्क करें।
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3