CodeGym /Java Blog /अनियमित /जावा में सुरक्षा: सर्वोत्तम अभ्यास
John Squirrels
स्तर 41
San Francisco

जावा में सुरक्षा: सर्वोत्तम अभ्यास

अनियमित ग्रुप में प्रकाशित
सर्वर अनुप्रयोगों में सबसे महत्वपूर्ण मेट्रिक्स में से एक सुरक्षा है। यह एक प्रकार की गैर-कार्यात्मक आवश्यकता है । जावा में सुरक्षा: सर्वोत्तम अभ्यास - 1सुरक्षा में कई घटक शामिल हैं। बेशक, सभी ज्ञात सुरक्षा सिद्धांतों और सुरक्षा उपायों को पूरी तरह से कवर करने के लिए एक से अधिक लेख की आवश्यकता होगी, इसलिए हम सबसे महत्वपूर्ण पर ध्यान केन्द्रित करेंगे। इस विषय में अच्छी तरह से वाकिफ व्यक्ति सभी प्रासंगिक प्रक्रियाओं को स्थापित कर सकता है, नए सुरक्षा छेद बनाने से बच सकता है, और किसी भी टीम में इसकी आवश्यकता होगी। बेशक, आपको यह नहीं सोचना चाहिए कि यदि आप इन प्रथाओं का पालन करते हैं तो आपका आवेदन 100% सुरक्षित होगा। नहीं! लेकिन यह उनके साथ निश्चित रूप से अधिक सुरक्षित होगा। चल दर।

1. जावा भाषा के स्तर पर सुरक्षा प्रदान करें

सबसे पहले, जावा में सुरक्षा भाषा की क्षमताओं के स्तर पर शुरू होती है। अगर कोई एक्सेस मॉडिफायर नहीं होता तो हम क्या करते? अराजकता के सिवा कुछ नहीं होगा। प्रोग्रामिंग भाषा हमें सुरक्षित कोड लिखने में मदद करती है और कई अंतर्निहित सुरक्षा सुविधाओं का भी उपयोग करती है:
  1. मजबूत टाइपिंग। जावा एक वैधानिक रूप से टाइप की जाने वाली भाषा है। यह रनटाइम पर टाइप-संबंधी त्रुटियों को पकड़ना संभव बनाता है।
  2. एक्सेस संशोधक। ये हमें आवश्यकतानुसार कक्षाओं, विधियों और क्षेत्रों तक पहुँच को अनुकूलित करने की अनुमति देते हैं।
  3. स्वचालित स्मृति प्रबंधन। इसके लिए, जावा डेवलपर्स के पास एक कचरा संग्राहक है जो हमें सब कुछ मैन्युअल रूप से कॉन्फ़िगर करने से मुक्त करता है। हां, कभी-कभी दिक्कतें आती हैं।
  4. बायटेकोड सत्यापन : जावा को बायटेकोड में संकलित किया जाता है, जिसे निष्पादन से पहले रनटाइम द्वारा जांचा जाता है।
इसके अतिरिक्त, Oracle की सुरक्षा अनुशंसाएँ हैं । बेशक, यह ऊंची भाषा में नहीं लिखा गया है और इसे पढ़ते हुए आपको कई बार नींद आ सकती है, लेकिन यह इसके लायक है। विशेष रूप से, जावा एसई के लिए सुरक्षित कोडिंग दिशानिर्देश नामक दस्तावेज़ महत्वपूर्ण है। यह सुरक्षित कोड लिखने के बारे में सलाह देता है। यह दस्तावेज़ भारी मात्रा में अत्यधिक उपयोगी जानकारी देता है। यदि आपके पास मौका है, तो आपको इसे जरूर पढ़ना चाहिए। इस सामग्री में आपकी रुचि जगाने के लिए, यहाँ कुछ रोचक सुझाव दिए गए हैं:
  1. सुरक्षा-संवेदनशील वर्गों को क्रमबद्ध करने से बचें। क्रमांकन क्रमबद्ध फ़ाइल में वर्ग इंटरफ़ेस को उजागर करता है, न कि उस डेटा का उल्लेख करने के लिए जो क्रमबद्ध है।
  2. डेटा के लिए परिवर्तनीय कक्षाओं से बचने का प्रयास करें। यह अपरिवर्तनीय वर्गों (जैसे थ्रेड सुरक्षा) के सभी लाभ प्रदान करता है। यदि आपके पास एक परिवर्तनशील वस्तु है, तो इससे अप्रत्याशित व्यवहार हो सकता है।
  3. लौटे परिवर्तनशील वस्तुओं की प्रतियां बनाएँ। यदि कोई विधि किसी आंतरिक परिवर्तनशील वस्तु का संदर्भ देती है, तो क्लाइंट कोड वस्तु की आंतरिक स्थिति को बदल सकता है।
  4. और इसी तरह…
मूल रूप से, जावा एसई के लिए सिक्योर कोडिंग गाइडलाइंस जावा कोड को सही और सुरक्षित तरीके से लिखने के टिप्स और ट्रिक्स का एक संग्रह है।

2. SQL इंजेक्शन भेद्यता को समाप्त करें

यह एक विशेष प्रकार की भेद्यता है। यह विशेष है क्योंकि यह सबसे प्रसिद्ध और सबसे आम कमजोरियों में से एक है। अगर आपको कंप्यूटर सुरक्षा में कभी दिलचस्पी नहीं रही है, तो आप इसके बारे में नहीं जानते होंगे। एसक्यूएल इंजेक्शन क्या है? यह एक डेटाबेस हमला है जिसमें अतिरिक्त SQL कोड इंजेक्ट करना शामिल है जहाँ इसकी अपेक्षा नहीं की जाती है। मान लीजिए कि हमारे पास एक तरीका है जो डेटाबेस को क्वेरी करने के लिए किसी प्रकार के पैरामीटर को स्वीकार करता है। उदाहरण के लिए, एक उपयोगकर्ता नाम। कमजोर कोड कुछ इस तरह दिखेगा:

// This method retrieves from the database all users with a certain name
public List findByFirstName(String firstName) throws SQLException {
   // Connect to the database
   Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
  
   // Compose a SQL database query with our firstName
   String query = "SELECT * FROM USERS WHERE firstName = " + firstName;
  
   // Execute the query
   Statement statement = connection.createStatement();
   ResultSet result = statement.executeQuery(query);

   // Use mapToUsers to convert the ResultSet into a collection of users.
   return mapToUsers(result);
}

private List mapToUsers(ResultSet resultSet) {
   // Converts to a collection of users
}
इस उदाहरण में, एक अलग लाइन पर एक SQL क्वेरी पहले से तैयार की जाती है। तो समस्या क्या है, है ना? शायद समस्या यह है कि String.format का उपयोग करना बेहतर होगा ? नहीं? खैर, फिर क्या? आइए अपने आप को एक परीक्षक के स्थान पर रखें और सोचें कि firstName के मान के रूप में क्या पारित किया जा सकता है । उदाहरण के लिए:
  1. हम अपेक्षित पास कर सकते हैं - एक उपयोगकर्ता नाम। तब डेटाबेस सभी उपयोगकर्ताओं को उस नाम के साथ वापस कर देगा।
  2. हम एक खाली स्ट्रिंग पास कर सकते हैं। फिर सभी उपयोगकर्ताओं को वापस कर दिया जाएगा।
  3. लेकिन हम निम्नलिखित को भी पास कर सकते हैं: "'; DROP TABLE USERS;"। और यहाँ अब हमारे पास हुउउउउगे समस्याएँ हैं। यह क्वेरी डेटाबेस से तालिका को हटा देगी। साथ में सारा डेटा। यह सब।
क्या आप उन समस्याओं की कल्पना कर सकते हैं जो इसके कारण होंगी? इसके अलावा आप जो चाहें लिख सकते हैं। आप सभी उपयोगकर्ताओं के नाम बदल सकते हैं। आप उनके पते मिटा सकते हैं. तोड़फोड़ की गुंजाइश बहुत अधिक है। इससे बचने के लिए, आपको तैयार क्वेरी के इंजेक्शन को रोकने की आवश्यकता है और इसके बजाय मापदंडों का उपयोग करके क्वेरी बनाएं। डेटाबेस क्वेरी बनाने का यही एकमात्र तरीका होना चाहिए। इस तरह आप इस भेद्यता को समाप्त कर सकते हैं। उदाहरण के लिए:

// This method retrieves from the database all users with a certain name
public List findByFirstName(String firstName) throws SQLException {
   // Connect to the database
   Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);

   // Create a parameterized query.
   String query = "SELECT * FROM USERS WHERE firstName = ?";

   // Create a prepared statement with the parameterized query
   PreparedStatement statement = connection.prepareStatement(query);
  
   // Pass the parameter's value
   statement.setString(1, firstName);

   // Execute the query
   ResultSet result = statement.executeQuery(query);

   // Use mapToUsers to convert the ResultSet into a collection of users.
   return mapToUsers(result);
}

private List mapToUsers(ResultSet resultSet) {
   // Converts to a collection of users
}
इस तरह भेद्यता से बचा जाता है। उन लोगों के लिए जो इस लेख की गहराई में जाना चाहते हैं, यहां एक बढ़िया उदाहरण दिया गया है । जब आप इस भेद्यता को समझते हैं तो आप कैसे जानेंगे? यदि आपको नीचे दिए गए कॉमिक में चुटकुला मिलता है, तो आपको शायद इस बात की स्पष्ट समझ है कि यह भेद्यता क्या है: डीजावा में सुरक्षा: सर्वोत्तम अभ्यास - 2

3. निर्भरताओं को स्कैन करें और उन्हें अद्यतन रखें

इसका क्या मतलब है? यदि आप नहीं जानते कि निर्भरता क्या है, तो मैं समझाता हूँ। एक निर्भरता कोड के साथ एक JAR संग्रह है जो किसी और के समाधान का पुन: उपयोग करने के लिए स्वचालित बिल्ड सिस्टम (मावेन, ग्रैडल, चींटी) का उपयोग करके एक परियोजना से जुड़ा है। उदाहरण के लिए, प्रोजेक्ट लोम्बोक , जो रनटाइम में हमारे लिए गेटर्स, सेटर आदि उत्पन्न करता है। बड़े अनुप्रयोगों में बहुत सारी और बहुत सारी निर्भरताएँ हो सकती हैं। कुछ सकर्मक हैं (अर्थात, प्रत्येक निर्भरता की अपनी निर्भरताएँ हो सकती हैं, और इसी तरह)। नतीजतन, हमलावर तेजी से खुले स्रोत की निर्भरता पर ध्यान दे रहे हैं, क्योंकि वे नियमित रूप से उपयोग किए जाते हैं और कई ग्राहकों को उनकी वजह से समस्या हो सकती है। यह सुनिश्चित करना महत्वपूर्ण है कि पूरे निर्भरता के पेड़ में कोई ज्ञात भेद्यता नहीं है (हाँ, यह एक पेड़ जैसा दिखता है)। इसे करने बहुत सारे तरीके हैं।

निर्भरता निगरानी के लिए Snyk का प्रयोग करें

Snyk सभी परियोजना निर्भरताओं की जांच करता है और ज्ञात कमजोरियों को चिन्हित करता है। आप Snyk पर पंजीकरण कर सकते हैं और GitHub के माध्यम से अपनी परियोजनाओं का आयात कर सकते हैं। जावा में सुरक्षा: सर्वोत्तम अभ्यास - 3इसके अलावा, जैसा कि आप ऊपर दी गई तस्वीर से देख सकते हैं, यदि एक नए संस्करण में भेद्यता तय की जाती है, तो Snyk इसे ठीक करने की पेशकश करेगा और एक पुल अनुरोध तैयार करेगा। आप इसे ओपन-सोर्स प्रोजेक्ट्स के लिए मुफ्त में इस्तेमाल कर सकते हैं। परियोजनाओं को नियमित अंतराल पर स्कैन किया जाता है, उदाहरण के लिए सप्ताह में एक बार, महीने में एक बार। मैंने पंजीकृत किया और अपने सभी सार्वजनिक रिपॉजिटरी को Snyk स्कैन में जोड़ा (इस बारे में कुछ भी खतरनाक नहीं है, क्योंकि वे पहले से ही सभी के लिए सार्वजनिक हैं)। Snyk ने तब स्कैन परिणाम दिखाया: जावा में सुरक्षा: सर्वोत्तम अभ्यास - 4और कुछ समय बाद, Snyk-bot ने परियोजनाओं में कई पुल अनुरोध तैयार किए जहाँ निर्भरता को अद्यतन करने की आवश्यकता है: जावा में सुरक्षा: सर्वोत्तम अभ्यास - 5और यह भी:जावा में सुरक्षा: सर्वोत्तम अभ्यास - 6यह नए संस्करणों के लिए कमजोरियों को खोजने और अद्यतनों की निगरानी के लिए एक बढ़िया उपकरण है।

गिटहब सुरक्षा लैब का प्रयोग करें

GitHub पर काम करने वाला कोई भी व्यक्ति इसके बिल्ट-इन टूल्स का लाभ उठा सकता है। आप इस दृष्टिकोण के बारे में उनके ब्लॉग पोस्ट में एनाउंसिंग गिटहब सिक्योरिटी लैब के बारे में अधिक पढ़ सकते हैं । बेशक, यह टूल Snyk से आसान है, लेकिन आपको निश्चित रूप से इसकी उपेक्षा नहीं करनी चाहिए। और तो और, ज्ञात कमजोरियों की संख्या केवल बढ़ेगी, इसलिए Snyk और GitHub Security Lab दोनों का विस्तार और सुधार जारी रहेगा।

सोनाटाइप डेपशील्ड सक्षम करें

यदि आप अपने रिपॉजिटरी को स्टोर करने के लिए गिटहब का उपयोग करते हैं, तो आप अपनी परियोजनाओं में मार्केटप्लेस में अनुप्रयोगों में से एक सोनटाइप डेपशील्ड जोड़ सकते हैं। इसका उपयोग निर्भरताओं के लिए परियोजनाओं को स्कैन करने के लिए भी किया जा सकता है। इसके अलावा, अगर यह कुछ पाता है, तो नीचे दिखाए गए उचित विवरण के साथ एक गिटहब समस्या उत्पन्न होगी:जावा में सुरक्षा: सर्वोत्तम अभ्यास - 7

4. गोपनीय डेटा को सावधानी से संभालें

हम वैकल्पिक रूप से "संवेदनशील डेटा" वाक्यांश का उपयोग कर सकते हैं। ग्राहक की व्यक्तिगत जानकारी, क्रेडिट कार्ड नंबर और अन्य संवेदनशील जानकारी को लीक करने से अपूरणीय क्षति हो सकती है। सबसे पहले, अपने एप्लिकेशन के डिज़ाइन पर करीब से नज़र डालें और निर्धारित करें कि क्या आपको वास्तव में इस या उस डेटा की आवश्यकता है। शायद आपको वास्तव में आपके पास मौजूद कुछ डेटा की आवश्यकता नहीं है - डेटा जो भविष्य के लिए जोड़ा गया था जो आया नहीं है और आने की संभावना नहीं है। इसके अतिरिक्त, आप कई अनजाने में लॉगिंग के माध्यम से ऐसे डेटा को लीक कर देते हैं। संवेदनशील डेटा को अपने लॉग में प्रवेश करने से रोकने का एक आसान तरीका डोमेन संस्थाओं (जैसे उपयोगकर्ता, छात्र, शिक्षक, आदि) के toString() तरीकों को साफ़ करना है। यह आपको गलती से गोपनीय क्षेत्रों को आउटपुट करने से रोकेगा। यदि आप toString () उत्पन्न करने के लिए लोम्बोक का उपयोग करते हैंविधि, आप किसी फ़ील्ड को toString() विधि के आउटपुट में उपयोग किए जाने से रोकने के लिए @ToString.Exclude एनोटेशन का उपयोग कर सकते हैं। साथ ही, बाहरी दुनिया को डेटा भेजते समय बहुत सावधान रहें। मान लीजिए कि हमारे पास एक HTTP समापन बिंदु है जो सभी उपयोगकर्ताओं के नाम दिखाता है। उपयोगकर्ता की विशिष्ट आंतरिक आईडी दिखाने की कोई आवश्यकता नहीं है। क्यों? क्योंकि एक हमलावर इसका उपयोग उपयोगकर्ता के बारे में अन्य, अधिक संवेदनशील जानकारी प्राप्त करने के लिए कर सकता है। उदाहरण के लिए, यदि आप JSON से/से POJO को क्रमबद्ध/डिसेरियलाइज़ करने के लिए जैक्सन का उपयोग करते हैं , तो आप @JsonIgnore और @JsonIgnoreProperties का उपयोग कर सकते हैंविशिष्ट क्षेत्रों के क्रमांकन/क्रमांकन को रोकने के लिए एनोटेशन। सामान्य तौर पर, आपको अलग-अलग स्थानों पर अलग-अलग POJO कक्षाओं का उपयोग करने की आवश्यकता होती है। इसका क्या मतलब है?
  1. डेटाबेस के साथ काम करते समय, एक प्रकार के POJO (एक इकाई) का उपयोग करें।
  2. व्यापार तर्क के साथ काम करते समय, एक इकाई को मॉडल में परिवर्तित करें।
  3. बाहरी दुनिया के साथ काम करते समय और HTTP अनुरोध भेजते समय, विभिन्न संस्थाओं (डीटीओ) का उपयोग करें।
इस तरह आप स्पष्ट रूप से परिभाषित कर सकते हैं कि कौन से क्षेत्र बाहर से दिखाई देंगे और कौन से नहीं।

मजबूत एन्क्रिप्शन और हैशिंग एल्गोरिदम का उपयोग करें

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

<!-- https://mvnrepository.com/artifact/com.google.crypto.tink/tink -->
<dependency>
   <groupid>com.google.crypto.tink</groupid>
   <artifactid>tink</artifactid>
   <version>1.3.0</version>
</dependency>
आइए देखें कि एन्क्रिप्शन और डिक्रिप्शन से जुड़े इस उदाहरण का उपयोग करके क्या करना है:

private static void encryptDecryptExample() {
   AeadConfig.register();
   KeysetHandle handle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256);

   String plaintext = "Elvis lives!";
   String aad = "Buddy Holly";

   Aead aead = handle.getPrimitive(Aead.class);
   byte[] encrypted = aead.encrypt(plaintext.getBytes(), aad.getBytes());
   String encryptedString = Base64.getEncoder().encodeToString(encrypted);
   System.out.println(encryptedString);

   byte[] decrypted = aead.decrypt(Base64.getDecoder().decode(encrypted), aad.getBytes());
   System.out.println(new String(decrypted));
}

पासवर्ड एन्क्रिप्ट करना

इस कार्य के लिए असममित एन्क्रिप्शन का उपयोग करना सबसे सुरक्षित है। क्यों? क्योंकि एप्लिकेशन को वास्तव में पासवर्ड डिक्रिप्ट करने की आवश्यकता नहीं होती है। यह मानक दृष्टिकोण है। वास्तव में, जब कोई उपयोगकर्ता पासवर्ड दर्ज करता है, तो सिस्टम इसे एन्क्रिप्ट करता है और पासवर्ड स्टोर में मौजूद चीज़ों से इसकी तुलना करता है। एक ही एन्क्रिप्शन प्रक्रिया की जाती है, इसलिए हम उम्मीद कर सकते हैं कि यदि सही पासवर्ड दर्ज किया गया है, तो वे मेल खाएंगे :) BCrypt और SCrypt यहां उपयुक्त हैं। दोनों कम्प्यूटेशनल रूप से जटिल एल्गोरिदम के साथ वन-वे फ़ंक्शंस (क्रिप्टोग्राफ़िक हैश) हैं जो एक लंबा समय लेते हैं। यह वही है जो हमें चाहिए, क्योंकि प्रत्यक्ष संगणना हमेशा के लिए (अच्छी तरह से, एक लंबा, लंबा समय) लेगी। वसंत सुरक्षा एल्गोरिदम की पूरी श्रृंखला का समर्थन करती है। हम SCryptPasswordEncoder और BCryptPasswordEncoder का उपयोग कर सकते हैं. वर्तमान में जिसे एक मजबूत एन्क्रिप्शन एल्गोरिथम माना जाता है, उसे अगले साल कमजोर माना जा सकता है। नतीजतन, हम निष्कर्ष निकालते हैं कि हमें नियमित रूप से हमारे द्वारा उपयोग किए जाने वाले एल्गोरिदम की जांच करनी चाहिए और आवश्यकतानुसार उन पुस्तकालयों को अपडेट करना चाहिए जिनमें एन्क्रिप्शन एल्गोरिदम शामिल हैं।

एक निष्कर्ष के बजाय

आज हमने सुरक्षा के बारे में बात की और स्वाभाविक रूप से बहुत सी चीजें पर्दे के पीछे रह गईं। मैंने अभी-अभी आपके लिए एक नई दुनिया का दरवाज़ा खोला है, एक ऐसी दुनिया जिसका अपना जीवन है। सुरक्षा राजनीति की तरह है: यदि आप अपने आप को राजनीति में व्यस्त नहीं रखते हैं, तो राजनीति स्वयं आपके साथ व्यस्त हो जाएगी। मैं पारंपरिक रूप से सुझाव देता हूं कि आप मुझे GitHub खाते पर फ़ॉलो करें । वहाँ मैं अपनी रचनाएँ पोस्ट करता हूँ जिसमें विभिन्न तकनीकें शामिल हैं जिनका मैं अध्ययन कर रहा हूँ और काम पर लागू कर रहा हूँ।

उपयोगी कड़ियां

  1. गुरु99: एसक्यूएल इंजेक्शन ट्यूटोरियल
  2. ओरेकल: जावा सुरक्षा संसाधन केंद्र
  3. ओरेकल: जावा एसई के लिए सुरक्षित कोडिंग दिशानिर्देश
  4. बाल्डुंग: जावा सुरक्षा की मूल बातें
  5. मध्यम: आपकी जावा सुरक्षा को सशक्त करने के लिए 10 युक्तियाँ
  6. Snyk: 10 जावा सुरक्षा सर्वोत्तम अभ्यास
  7. गिटहब: घोषणा गिटहब सुरक्षा प्रयोगशाला: दुनिया के कोड को एक साथ सुरक्षित करना
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION