काफी पहले से ही NodeJS की लोकप्रियता के बारे में कहा जा चुका है। अनुप्रयोगों की संख्या में वृद्धि स्पष्ट है - नोडजेएस सीखने में काफी आसान है, पुस्तकालयों की एक बड़ी संख्या है, साथ ही साथ गतिशील रूप से विकसित पारिस्थितिकी तंत्र भी है।हमने NWJS डेवलपर्स के लिए OWASP चीट शीट्स पर आधारित सिफारिशें कीं, ताकि एप्लिकेशन विकसित करते समय सुरक्षा संबंधी समस्याओं का पूर्वानुमान लगाने में मदद मिल सके।NodeJS अनुप्रयोगों के लिए सुरक्षा सिफारिशें निम्नलिखित श्रेणियों में विभाजित की जा सकती हैं:- अनुप्रयोग विकास के दौरान सुरक्षा;
- सर्वर सुरक्षा;
- प्लेटफ़ॉर्म सुरक्षा;
अनुप्रयोग विकास सुरक्षा
कॉलबैक फ़ंक्शंस से बचें कॉलबैक फ़ंक्शंस का उपयोग करना (कॉलबैक) NodeJS की सबसे बड़ी शक्तियों में से एक है, हालांकि जब कॉलबैक घोंसले का शिकार कर रहे हैं, तो आप आसानी से कार्यों में से एक में त्रुटि को संभालने के लिए भूल सकते हैं। कॉलबैक नरक से बचने का एक तरीका वादों का उपयोग करना है। यहां तक कि अगर आप जिस मॉड्यूल का उपयोग कर रहे हैं वह वादों के साथ काम करने का समर्थन नहीं करता है, तो आप हमेशा Promise.promisifyAll () का उपयोग कर सकते हैं। लेकिन वादों का उपयोग करते हुए भी, यह घोंसले के शिकार पर ध्यान देने योग्य है। कॉलबैक नरक त्रुटि से पूरी तरह से बचने के लिए, वादों की "सपाट" श्रृंखला से चिपके रहें।कॉलबैक नरक उदाहरण:function func1(name, callback) {
setTimeout(function() {
}, 500);
}
function func2(name, callback) {
setTimeout(function() {
}, 100);
}
function func3(name, callback) {
setTimeout(function() {
}, 900);
}
function func4(name, callback) {
setTimeout(function() {
}, 3000);
}
func1("input1", function(err, result1){
if(err){
}
else {
func2("input2", function(err, result2){
if(err){
}
else{
func3("input3", function(err, result3){
if(err){
}
else{
func4("input 4", function(err, result4){
if(err){
}
else {
}
});
}
});
}
});
}
});
समतल श्रृंखला वादों का उपयोग करते हुए समान कोड:function func1(name, callback) {
setTimeout(function() {
}, 500);
}
function func2(name, callback) {
setTimeout(function() {
}, 100);
}
function func3(name, callback) {
setTimeout(function() {
}, 900);
}
function func4(name, callback) {
setTimeout(function() {
}, 3000);
}
func1("input1")
.then(function (result){
return func2("input2");
})
.then(function (result){
return func3("input3");
})
.then(function (result){
return func4("input4");
})
.catch(function (error) {
});
अनुरोध का आकार सीमित करें। अनुरोधनिकाय को पार्स करना काफी संसाधन-गहन संचालन हो सकता है। यदि आप अनुरोध के आकार को सीमित नहीं करते हैं, तो हमलावर बड़े पर्याप्त अनुरोध भेज सकेंगे जो सभी डिस्क स्थान को भर सकते हैं या सभी सर्वर संसाधनों को समाप्त कर सकते हैं, लेकिन साथ ही, सभी मामलों के लिए अनुरोध आकार को सीमित करना गलत हो सकता है, क्योंकि अनुरोध हैं, जैसे कि एक फ़ाइल डाउनलोड करना। इसलिए, विभिन्न प्रकार की सामग्री के लिए सीमा निर्धारित करने की सिफारिश की जाती है। उदाहरण के लिए, एक्सप्रेस ढांचे का उपयोग करते हुए, इसे निम्नानुसार लागू किया जा सकता है:app.use(express.urlencoded({ limit: "1kb" }));
app.use(express.json({ limit: "1kb" }));
app.use(express.multipart({ limit:"10mb" }));
यह ध्यान दिया जाना चाहिए कि एक हमलावर अनुरोध सामग्री के प्रकार को बदल सकता है और प्रतिबंधों को दरकिनार कर सकता है, इसलिए, यह जांचना आवश्यक है कि अनुरोध की सामग्री अनुरोध शीर्षक में निर्दिष्ट सामग्री के प्रकार से मेल खाती है या नहीं। यदि सामग्री के प्रकार की जाँच प्रदर्शन को प्रभावित करती है, तो आप केवल कुछ प्रकारों या प्रश्नों की जाँच कर सकते हैं जो एक निश्चित आकार से बड़े हैं।ईवेंट लूप को ब्लॉक नकरें भाषा का एक महत्वपूर्ण घटक ईवेंट लूप है, जो आपको केवल ऑपरेशन पूरा होने का इंतजार किए बिना निष्पादन संदर्भ को स्विच करने की अनुमति देता है। हालांकि, ऐसे ब्लॉकिंग ऑपरेशन हैं जिनके पूरा होने पर कोड जारी रखने से पहले NodeJS को इंतजार करना पड़ता है। उदाहरण के लिए, अधिकांश तुल्यकालिक तरीके अवरुद्ध हैं:const fs = require('fs');
fs.unlinkSync('/file.txt');
अतुल्यकालिक रूप से इस तरह के ऑपरेशन करने की सिफारिश की जाती है:const fs = require('fs');
fs.unlink('/file.txt', (err) => {
if (err) throw err;
});
इसी समय, यह मत भूलो कि असिंक्रोनस कॉल के बाद खड़े हुए कोड को पिछले ऑपरेशन के पूरा होने की प्रतीक्षा किए बिना निष्पादित किया जाएगा।उदाहरण के लिए, नीचे दिए गए कोड में, फ़ाइल को पढ़ने से पहले हटा दिया जाएगा, जिससे दौड़ की स्थिति पैदा हो सकती है।const fs = require('fs');
fs.readFile('/file.txt', (err, data) => {
});
fs.unlinkSync('/file.txt');
इससे बचने के लिए, आप एक नॉन-ब्लॉकिंग फ़ंक्शन में सभी ऑपरेशन लिख सकते हैं:const fs = require('fs');
fs.readFile('/file.txt', (err, data) => {
fs.unlink('/file.txt', (err) => {
if (err) throw err;
});
});
इनपुट फ़ील्ड कीजाँच करें। इनपुट फ़ील्ड की जाँच किसी भी एप्लिकेशन की सुरक्षा का एक महत्वपूर्ण हिस्सा है। सत्यापन त्रुटियां आपके आवेदन को कई प्रकार के हमलों के लिए तुरंत असुरक्षित हो सकती हैं: sql इंजेक्शन, xss, कमांड इंजेक्शन, और अन्य। फ़ॉर्म सत्यापन को सरल बनाने के लिए, आप सत्यापनकर्ता पैकेज, मोंगो-एक्सप्रेस-सैनिटाइज़ का उपयोग कर सकते हैं।उपयोगकर्ता डेटासे बचना नियमों में से एक है जो आपको अपने आप को xss हमलों से बचाने में मदद करेगा उपयोगकर्ता डेटा को ढाल देना है। आप इसके लिए एस्केप-html या नोड-एसपीआई लाइब्रेरी का उपयोग कर सकते हैं।लॉग रखेंइसके अलावा, यह त्रुटियों को डीबग करने में मदद करेगा, लॉगिंग का उपयोग घटनाओं का जवाब देने के लिए किया जा सकता है। आप यहां लॉग इन करने की आवश्यकता के बारे में अधिक पढ़ सकते हैं ।। सबसे लोकप्रिय NodeJS लॉगिंग पैकेजों में से एक विंस्टन और ब्यान है। नीचे दिए गए उदाहरण से पता चलता है कि विंस्टन का उपयोग कंसोल और फ़ाइल दोनों के आउटपुट लॉग में कैसे किया जाता है:var logger = new (Winston.Logger) ({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'application.log' })
],
level: 'verbose'
});
घटनाओं के चक्र को नियंत्रित करेंयदि आपका सर्वर गहन नेटवर्क यातायात की स्थिति में है, तो उपयोगकर्ता आपकी सेवा की उपलब्धता के साथ कठिनाइयों का अनुभव कर सकते हैं। यह अनिवार्य रूप से एक DoS हमला है। इस स्थिति में, आप प्रतिक्रिया समय को ट्रैक कर सकते हैं और, यदि यह निर्दिष्ट समय से अधिक है, तो संदेश को 503 सर्वर टू में व्यस्त करें। टोबैसी-जेएस मॉड्यूल मदद कर सकता है।मॉड्यूल का उपयोग करने का एक उदाहरण:var toobusy = require('toobusy-js');
var express = require('express');
var app = express();
app.use(function(req, res, next) {
if (toobusy()) {
res.send(503, "Server Too Busy");
} else {
next();
}
});
जानवर बल के खिलाफ सावधानी बरतें।फिर से, मॉड्यूल बचाव के लिए आते हैं। उदाहरण के लिए, एक्सप्रेस-ब्रूट या एक्सप्रेस-बाउंसर। उपयोग उदाहरण:var bouncer = require('express-bouncer');
bouncer.whitelist.push('127.0.0.1');
bouncer.blocked = function (req, res, next, remaining) {
res.send(429, "Too many requests have been made. Please wait " + remaining/1000 + " seconds.");
};
app.post("/login", bouncer.block, function(req, res) {
if (LoginFailed){ }
else {
bouncer.reset( req );
}
});
CAPTCHA का उपयोग करना एक और आम क्रूर बल प्रतिवाद है। कैप्चा को लागू करने में मदद करने के लिए अक्सर इस्तेमाल किया जाने वाला मॉड्यूल svg-captcha है।CSRF टोकन का उपयोग करें CSRFहमलों से बचाव के सबसे विश्वसनीय तरीकों में से एक CSRF टोकन का उपयोग करना है। टोकन को उच्च एन्ट्रापी के साथ उत्पन्न किया जाना चाहिए, कड़ाई से जाँच की जानी चाहिए और उपयोगकर्ता के सत्र से जुड़ा होना चाहिए। CSRF टोकन के संचालन को सुनिश्चित करने के लिए, आप csurf मॉड्यूल का उपयोग कर सकते हैं।उपयोग उदाहरण:var csrf = require('csurf');
csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, function(req, res) {
res.render('send', { csrfToken: req.csrfToken() })
})
app.post('/process', parseForm, csrfProtection, function(req, res) {
res.send('data is being processed');
});
पृष्ठ पर छिपे हुए फ़ील्ड में टोकन जोड़ना न भूलें:<input type="hidden" name="_csrf" value="{{ csrfToken }}">
आप हमारे लेख में CSRF टोकन के बारे में अधिक पढ़ सकते हैं ।अनावश्यक मार्गों को हटा दें।वेब एप्लिकेशन में वे पृष्ठ नहीं होने चाहिए जो उपयोगकर्ताओं द्वारा उपयोग नहीं किए जाते हैं, क्योंकि इससे हमले की सतह बढ़ सकती है। इसलिए, सभी अप्रयुक्त एपीआई मार्गों को अक्षम किया जाना चाहिए। आपको विशेष रूप से इस सवाल पर ध्यान देना चाहिए यदि आप Sails या पंख चौखटे का उपयोग करते हैं, क्योंकि वे स्वचालित रूप से API समापन बिंदु उत्पन्न करते हैं।खुद को एचपीपी (HTTP पैरामीटर प्रदूषण) से सुरक्षित रखेंडिफ़ॉल्ट रूप से, एक्सप्रेस अनुरोध से सभी मापदंडों को एक सरणी में जोड़ता है। OWASP hpp मॉड्यूल का उपयोग करने की सिफारिश करता है, जो req.query और / या req.body से सभी पैरामीटर मानों को अनदेखा करता है और केवल डुप्लिकेट लोगों के बीच अंतिम मान का चयन करता है।var hpp = require('hpp');
app.use(hpp());
लौटाए गए मानों की निगरानी करें।उदाहरण के लिए, उपयोगकर्ता तालिका महत्वपूर्ण डेटा संग्रहीत कर सकती है: पासवर्ड, ईमेल पता, जन्म तिथि, आदि। इसलिए, केवल आवश्यक डेटा वापस करना महत्वपूर्ण है।उदाहरण के लिए: exports.sanitizeUser = function(user) {
return {
id: user.id,
username: user.username,
fullName: user.fullName
};
};
डिस्क्रिप्टर का उपयोग करें। डिस्क्रिप्टर्स का उपयोगविभिन्न कार्यों के लिए एक संपत्ति के व्यवहार का वर्णन करने के लिए किया जा सकता है: लिखने योग्य - चाहे संपत्ति के मूल्य को बदला जा सके, गणना करने योग्य - चाहे संपत्ति का उपयोग for..in लूप में हो, विन्यास योग्य - क्या संपत्ति को फिर से लिखा जा सकता है। सूचीबद्ध गुणों पर ध्यान देने की सिफारिश की जाती है, क्योंकि किसी वस्तु की संपत्ति को परिभाषित करते समय, ये सभी विशेषताएँ डिफ़ॉल्ट रूप से सही पर सेट होती हैं। आप गुणों का मूल्य निम्नानुसार बदल सकते हैं:var o = {};
Object.defineProperty(o, "a", {
writable: true,
enumerable: true,
configurable: true,
value: "A"
});
ACLs का उपयोग करें Aclभूमिकाओं के आधार पर डेटा एक्सेस को अलग करने में मदद कर सकता है। उदाहरण के लिए, अनुमति जोड़ना इस तरह दिखता है:
acl.allow('guest', 'blogs', 'view')
acl.allow('member', 'blogs', ['edit', 'view', 'delete'])
बिनाकिसी अपवाद के पकड़ें डिफ़ॉल्ट रूप से, बिना किसी अपवाद के घटना में, NodeJS वर्तमान स्टैक ट्रेस को फेंक देगा और निष्पादन थ्रेड को समाप्त कर देगा। हालाँकि, NodeJS आपको इस व्यवहार को अनुकूलित करने की अनुमति देता है। एक अनियोजित अपवाद की स्थिति में, एक अनिर्दिष्ट अपवाद घटना को उठाया जाता है, जिसे प्रक्रिया ऑब्जेक्ट का उपयोग करके पकड़ा जा सकता है:process.on("uncaughtException", function(err) {
process.exit();
});
यह याद रखने योग्य है कि जब कोई अनएक्सपेक्टेड अपवाद होता है, तो अप्रत्याशित त्रुटियों से बचने के लिए जेड प्रक्रिया को पूरा करने से पहले सभी आवंटित संसाधनों (उदाहरण के लिए, फ़ाइल डिस्क्रिप्टर और हैंडलर) को साफ़ करना आवश्यक है। यह दृढ़ता से हतोत्साहित किया जाता है कि यदि कोई अप्रत्यक्ष अपवाद होता है तो कार्यक्रम चलता रहता है।इसके अलावा, त्रुटि संदेश प्रदर्शित करते समय, उपयोगकर्ता को विस्तृत त्रुटि जानकारी, जैसे स्टैक ट्रेस का खुलासा नहीं करना चाहिए।सर्वर सुरक्षा
कुकीज़ के साथ काम करते समय हेडर के लिए झंडे सेट करें।कई झंडे हैं जो हमलों से बचाने में मदद कर सकते हैं जैसे कि xss और csrf: httpOnly, जो जावास्क्रिप्ट के माध्यम से कुकीज़ तक पहुंच को रोकता है; सुरक्षित - केवल HTTPS और SameSite के माध्यम से कुकीज़ भेजने की अनुमति देता है, जो कुकीज़ को तृतीय-पक्ष संसाधन में स्थानांतरित करने की क्षमता निर्धारित करता है।उपयोग उदाहरण:var session = require('express-session');
app.use(session({
secret: 'your-secret-key',
key: 'cookieName',
cookie: { secure: true, httpOnly: true, path: '/user', sameSite: true}
}));
सुरक्षा के लिए HTTP हेडर सेट करेंनिम्नलिखित हेडर और उदाहरण हैं कि उन्हें कई आम हमलों से खुद को बचाने में आपकी मदद करने के लिए उन्हें कैसे कनेक्ट किया जाए। हेडर हेलमेट मॉड्यूल का उपयोग कर स्थापित कर रहे हैं• सख्त-परिवहन-सुरक्षा: HTTP सख्त परिवहन सुरक्षा (HSTS) ब्राउज़र बताता है कि आवेदन केवल HTTPS के माध्यम से पहुँचा जा सकता हैapp.use(helmet.hsts());
app.use(helmet.hsts("<max-age>", "<includeSubdomains>"));
• एक्स-फ्रेम-ऑप्शंस: यह निर्धारित करता है कि पेज का उपयोग फ्रेम, आईफ्रेम, एम्बेड या ऑब्जेक्ट में किया जा सकता है या नहींapp.use(hemlet.xframe());
helmet.xframe('sameorigin');
helmet.xframe('allow-from', 'http://alloweduri.com');
• X-XSS- सुरक्षा: यदि यह एक प्रतिबिंबित XSS हमले का पता लगाता है तो ब्राउज़र पृष्ठ को लोड करने से रोकने के लिए अनुमति देता है।var xssFilter = require('x-xss-protection');
app.use(xssFilter());
• X- सामग्री-प्रकार-विकल्प: MIME प्रकारों के उपयोग से हमलों को रोकने के लिए उपयोग किया जाता हैapp.use(helmet.noSniff());
• सामग्री-सुरक्षा-नीति: XSS और डेटा इंजेक्शन हमलों जैसे हमलों को रोकता हैconst csp = require('helmet-csp')
app.use(csp({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
frameAncestors: ["'none'"],
imgSrc: ["'self'", "'http://imgexample.com'"],
styleSrc: ["'none'"]
}
}))
• कैश-कंट्रोल और प्रागमा: कैशिंग के प्रबंधन के लिए, विशेष रूप से यह हेडर उन पृष्ठों के लिए उपयोगी हो सकता है जिनमें संवेदनशील डेटा होता है। हालाँकि, याद रखें कि सभी पृष्ठों पर कैशिंग अक्षम करने से प्रदर्शन प्रभावित हो सकता है।app.use(helmet.noCache());
• एक्स-डाउनलोड-विकल्प: हेडर इंटर एक्सप्लोरर को डाउनलोड की गई फ़ाइलों को निष्पादित करने से रोकता हैapp.use(helmet.ieNoOpen());
• उम्मीद-सीटी: प्रमाणपत्र पारदर्शिता - एसएसएल प्रमाणपत्रों की बुनियादी सुविधाओं के साथ कुछ समस्याओं को हल करने के लिए बनाया गया एक तंत्र, यह शीर्षक ब्राउज़र को सीटी लॉग में अतिरिक्त प्रमाणपत्र सत्यापन की आवश्यकता के बारे में बताता है।var expectCt = require('expect-ct');
app.use(expectCt({ maxAge: 123 }));
app.use(expectCt({ enforce: true, maxAge: 123 }));
app.use(expectCt({ enforce: true, maxAge: 123, reportUri: 'http://example.com'}));
• एक्स-पावर्ड-बाय: एक वैकल्पिक हैडर जिसका उपयोग सर्वर पर उपयोग की जाने वाली तकनीक को इंगित करने के लिए किया जाता है। आप इस शीर्ष लेख को इस प्रकार छिपा सकते हैं:app.use(helmet.hidePoweredBy());
इसके अलावा, आप अपने द्वारा उपयोग की जाने वाली तकनीकों के बारे में वास्तविक जानकारी छिपाने के लिए मान बदल सकते हैं:app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }));
मंच की सुरक्षा
अपने पैकेजों को अपडेट करेंआपके आवेदन की सुरक्षा आपके द्वारा उपयोग किए जाने वाले पैकेजों की सुरक्षा पर निर्भर करती है, इसलिए पैकेज के नवीनतम संस्करण का उपयोग करना महत्वपूर्ण है। यह सुनिश्चित करने के लिए कि आपके द्वारा उपयोग किए जा रहे पैकेज में ज्ञात कमजोरियाँ नहीं हैं, आप विशेष OWASP सूची का उपयोग कर सकते हैं । आप लाइब्रेरी का उपयोग भी कर सकते हैं जो ज्ञात कमजोरियों के लिए पैकेजों की जांच करता है Retire.js।असुरक्षित कार्यों का उपयोग न करें।ऐसे कार्य हैं जिन्हें जब भी संभव हो त्यागने की सिफारिश की जाती है। इन कार्यों में से एक है eval (), जो एक तर्क के रूप में लिया गया स्ट्रिंग निष्पादित करता है। उपयोगकर्ता इनपुट के साथ संयोजन में, इस फ़ंक्शन का उपयोग करने से दूरस्थ कोड निष्पादन भेद्यता हो सकती है, क्योंकि इसी तरह के कारणों के लिए, child_process.exec का उपयोग करना भी असुरक्षित है, क्योंकि फ़ंक्शन प्राप्त तर्कों को बिन / श पास करता है।इसके अलावा, कई मॉड्यूल हैं जिन्हें आपको सावधानी के साथ उपयोग करना चाहिए। उदाहरण के लिए, फ़ाइलों के साथ काम करने के लिए fs मॉड्यूल। यदि एक निश्चित तरीके से उत्पन्न उपयोगकर्ता इनपुट को एक फ़ंक्शन में पास किया जाता है, तो आपका एप्लिकेशन स्थानीय फ़ाइल और निर्देशिका ट्रैवर्सल को शामिल करने के लिए असुरक्षित हो सकता है।Vm मॉड्यूल, जो V8 वर्चुअल मशीन पर कोड को संकलित करने और चलाने के लिए एक एपीआई प्रदान करता है, का उपयोग केवल सैंडबॉक्स में किया जाना चाहिए।यहां आप अन्य कार्यों से खुद को परिचित कर सकते हैं जो आपके आवेदन को असुरक्षित बना सकते हैं।नियमित अभिव्यक्तियों का उपयोग करके सावधान रहें।एक नियमित अभिव्यक्ति लिखी जा सकती है ताकि आप एक ऐसी स्थिति प्राप्त कर सकें जहां अभिव्यक्ति तेजी से बढ़ेगी, जिससे सेवा से वंचित हो सकता है। ऐसे हमलों को ReDoS कहा जाता है। यह जांचने के लिए कई उपकरण हैं कि क्या नियमित अभिव्यक्ति सुरक्षित हैं, जिनमें से एक वल्न-रेगेक्स-डिटेक्टर है।समय-समय पर लिंटर चलाएंविकास के दौरान, सभी सुरक्षा सिफारिशों को ध्यान में रखना कठिन है, और जब टीम विकास की बात आती है, तो टीम के सभी सदस्यों द्वारा नियमों का अनुपालन करना आसान नहीं होता है। ऐसे उद्देश्यों के लिए, स्थैतिक सुरक्षा विश्लेषण के लिए उपकरण हैं। इस तरह के उपकरण, आपके कोड को निष्पादित किए बिना, इसमें कमजोरियों की तलाश करते हैं। इसके अलावा, लिंटर आपको कोड के स्थानों को खोजने के लिए कस्टम नियम जोड़ने की अनुमति देता है जो असुरक्षित हो सकते हैं। सबसे अधिक इस्तेमाल किए जाने वाले लिंटर्स ESLint और JSHint हैं।सख्त मोड का उपयोग करें।जावास्क्रिप्ट में कई असुरक्षित और अप्रचलित कार्य हैं जिनका उपयोग नहीं किया जाना चाहिए। इन कार्यों का उपयोग करने की संभावना को बाहर करने के लिए, सख्त मोड भी प्रदान किया जाता है।सामान्य सुरक्षा सिद्धांतों का पालन करेंवर्णित सिफारिशें NodeJS पर ध्यान केंद्रित करती हैं, लेकिन सामान्य सुरक्षा सिद्धांतों के बारे में नहीं भूलती हैं जो कि इस्तेमाल किए गए प्लेटफॉर्म की परवाह किए बिना मनाया जाना चाहिए।