आप डेस्कटॉप एप्लिकेशन से डेटाबेस सुरक्षा कैसे संभालते हैं?


12

लगभग 10 वर्षों तक मैंने SQL सर्वर डेटा स्टोर के साथ विभिन्न इन-हाउस डेस्कटॉप क्लाइंट एप्लिकेशन पर काम किया है। शायद ही मैंने इन परियोजनाओं को शुरू किया था - अधिकांश अधिग्रहण कार्य हैं।

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

आप वास्तव में इस उपयोगकर्ता नाम और पासवर्ड को प्रभावी ढंग से छिपा नहीं सकते हैं जो एप्लिकेशन डेटाबेस तक पहुंचने के लिए उपयोग करता है। वे आमतौर पर एक iniया configफ़ाइल में संग्रहीत होते हैं , या संभवतः निष्पादन योग्य में बेक किए जाते हैं। सभी मामलों में, यदि वे थोड़ा खुदाई करते हैं, तो वे उपयोगकर्ता को दिखाई देते हैं। एक मामले में हमने वास्तव में एक configफ़ाइल का उपयोग किया था लेकिन इसे एन्क्रिप्ट किया था, लेकिन निश्चित रूप से एन्क्रिप्शन कुंजी को निष्पादन योग्य में संग्रहीत किया जाना था (हम इस की सीमाओं के लिए भोले नहीं थे, लेकिन इसने प्रभावी रूप से उन लोगों को रोकना बंद कर दिया, जो काफी समझदार थे configफाइलों में देखना )।

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

मुझे यह जानने में दिलचस्पी है कि इस समस्या के आसपास अन्य सिस्टम क्या कर सकते हैं। यहाँ मेरे द्वारा चुने गए विकल्प हैं:

  1. उपयोगकर्ता और भूमिकाओं की सूची को बनाए रखने के लिए SQL सर्वर के सुरक्षा तंत्र का उपयोग करें, और डेस्कटॉप एप्लिकेशन को T-SQL प्रश्नों के माध्यम से उपयोगकर्ताओं को जोड़ने और हटाने के लिए बनाएं।
  2. डेटाबेस से सीधे कनेक्ट करने के बजाय, सर्वर पर चलने वाली कुछ प्रकार की वेब सेवा बनाएं और प्रमाणीकरण तर्क को वहां रखें। हर अनुरोध सुरक्षा सत्यापन करें।

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

दूसरा सिर्फ एक प्रमुख प्रदर्शन समस्या की तरह लगता है, और बहुत सारे अतिरिक्त काम, प्लस आप आसानी से ORM मैपर्स जैसे NHibernate (मुझे लगता है) का उपयोग नहीं कर सकते हैं।

क्या किसी के पास इसका अनुभव है? सर्वोत्तम प्रथाएं?

संपादित करें

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


बाइंडिंग के विषय पर; ORM जैसे NHibernate का उपयोग नहीं करना (मुझे लगता है) एक गैर मुद्दा है। यदि आप एक उदाहरण के रूप में वेब सेवाओं का उपयोग करते हैं, तो आप अपने डेटा को एक्सएमएल में कुशलता से बांधने के कई तरीके पाएंगे।
जसकॉं

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

@ जीबीजैनब - यकीन है, मैं आज दोपहर को पूरी वास्तुकला बदल दूंगा। :)
स्कॉट व्हिटलॉक

मुझे लगता है कि आप इसे बदलने से पहले किसी को हैक करने तक इंतजार कर सकते हैं, लेकिन उज्ज्वल पक्ष पर, कम से कम तब आपको अपने बॉस को फिर से आर्किटेक्चर को फंड करने के लिए कोई समस्या नहीं होगी :-)
gbjbaanb

आप किसी उपयोगकर्ता को किसी अन्य के रिकॉर्ड को अपडेट करने से रोक सकते हैं - संग्रहीत कार्यविधि को रिकॉर्ड को अपडेट करने का एकमात्र तरीका है और उस उपयोगकर्ता का उपयोग करने से जो क्वेरी के भाग के रूप में खरीद रहा है। देखें CURRENT_USER
gbjbaanb

जवाबों:


9

मुझे डर है कि वेब सेवा की परत जोड़ने से आपकी समस्या का सही समाधान हो सकता है।

अंतर्निहित डेटाबेस कार्यान्वयन से क्लाइंट को अलग करना संभवतः आपको लंबे समय में भी मदद करेगा।

वेब सेवा परत को जोड़ने से जरूरी नहीं कि प्रदर्शन को नुकसान पहुंचे ...

वास्तव में, एक उपयुक्त एपीआई के साथ, एक वेब सेवा वास्तव में WAN पर कई राउंड ट्रिप की आवश्यकता के बजाय, डेटा सेंटर LAN के भीतर कई डेटाबेस प्रश्नों को एक साथ बैच कर, प्रदर्शन में सुधार कर सकती है।

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

एक सर्वर लेयर सुरक्षा को जोड़ता है जिसे आप संभवतः दूरस्थ क्लाइंट पर चलने वाले ऐप्स के साथ सुनिश्चित नहीं कर सकते। क्लाइंट पर चलने वाली कोई भी चीज़ "हैक" की जा सकती है और इसे वास्तव में किसी भी तरह से विश्वसनीय नहीं माना जाना चाहिए। आपको केवल क्लाइंट में ही प्रेजेंटेशन लॉजिक डालना चाहिए, और हार्डवेयर पर कुछ भी होस्ट करना चाहिए, जिस पर आपका पूरा नियंत्रण हो।

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

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


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

3
यह एक परत जोड़ता है, लेकिन जरूरी नहीं कि रखरखाव हो। इस बात पर विचार करें कि सेवा में रखे गए सभी तर्कों के साथ, क्लाइंट नहीं, उपयोगकर्ताओं को अपने क्लाइंट एप्लिकेशन को अपडेट करने की आवश्यकता के बिना परिवर्तन 'लुढ़का' जा सकता है।
ग्रैंडमास्टरबी

5

Jmoreno द्वारा उत्तर के समान, आप संग्रहीत प्रक्रियाओं पर EXECUTE अनुमतियों से अलग हर चीज के लिए एक उपयोगकर्ता की पहुँच से इनकार कर सकते हैं, फिर स्वामित्व प्रक्रिया का लाभ उठाते हुए संग्रहीत कार्यविधि को तालिकाओं पर आवश्यक कार्य निष्पादित करें।

विवरण के लिए यहां देखें https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx

जब उपयोगकर्ता अपने उपयोगकर्ता नाम / पासवर्ड क्लाइंट पक्ष में प्रवेश करता है, तो मैं उन्हें संग्रहीत करता हूं और हर संग्रहीत कार्यविधि कॉल में पैरामीटर के रूप में भेजता हूं। आप वांछित ऑपरेशन करने से पहले एक तालिका में संग्रहीत मूल्यों के खिलाफ उन्हें सत्यापित कर सकते हैं।

निश्चित रूप से सुरक्षा में अंतिम शब्द नहीं है, लेकिन यह आवश्यक हो सकता है यदि आपके पीसी में जेनेरिक लॉगिन हैं, तो अनुमतियों के लिए AD समूहों का उपयोग करने की आपकी क्षमता को सीमित कर सकते हैं, या आपके पास AD तक ही सीमित पहुंच है।


2

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

बेशक यह हमेशा संभव नहीं है, लेकिन यह हो सकता है। सबसे अच्छा तरीका आपकी आवश्यकताओं और संसाधनों पर निर्भर करेगा।


यह कुछ ऐसा है जिसे मैंने नहीं माना था। मुझे यकीन नहीं है कि यह एक महान फिट है, लेकिन यह काम करेगा।
स्कॉट व्हिटलॉक

1

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

आप क्लाइंट और डेटाबेस (और अन्य संसाधनों) के बीच मध्यस्थ के रूप में कार्य करने के लिए एक एप्लिकेशन सर्वर बनाते हैं। एप्लिकेशन सर्वर आपके एप्लिकेशन आधारित प्रमाणीकरण को संभालता है और क्लाइंट की ओर से कार्रवाई करता है। वास्तव में, आदर्श रूप से आप अपने क्लाइंट में कोई SQL नहीं कर रहे हैं - बल्कि आप ऐप सर्वर पर विधियों को कॉल करते हैं। एप्लिकेशन सर्वर सभी डेटा हेरफेर को हैंडल करेगा।

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


इससे भी बेहतर, अगर (या जब) कोई आपके डेस्कटॉप (या वेब-आधारित समकक्ष में वेबसर्वर) को हैक करता है, तो हमलावर के पास ओएस तक पूर्ण पहुंच हो सकती है, लेकिन उनके पास अभी भी डीबी तक पहुंच नहीं है। और इसलिए वे तब "सेलेक्ट * यूजर्स से" नहीं चला सकते हैं, जो एक फाइल पर ले जाया जाता है, जिसे वे ले जाते हैं, अपने अवकाश पर दरार करते हैं और अपने सीईओ को मीडिया को समझाते हैं कि आपके सुरक्षित सिस्टम से समझौता क्यों किया गया। यदि आप DB पर स्पोक्स का उपयोग करते हैं जो केवल निष्पादन की अनुमति देता है, तो हमलावर आपके ऐप को भी गंभीर रूप से हैक कर सकता है और वे अभी भी आपके पूरे उपयोगकर्ता डेटाबेस को प्राप्त नहीं कर सकते हैं।
gbjbaanb

1

तकनीक थोड़ी बदल गई है। यदि आप प्रत्येक उपयोगकर्ता को स्वयं डेटाबेस में प्रमाणित करते हैं, और डेटाबेस भूमिकाओं का उपयोग करते हैं, तो आप अब इस समस्या को हल करने के लिए एक अद्यतन करने योग्य दृश्य का उपयोग कर सकते हैं, कम से कम SQL सर्वर में।

यहाँ एक तालिका के लिए एक अद्यतन योग्य दृश्य कैसा दिख सकता है, जिसे SomeTableउस तालिका की प्रत्येक पंक्ति एक कर्मचारी से जुड़ी हुई है। कर्मचारी को उनसे जुड़ी पंक्तियों को देखने में सक्षम होना चाहिए, और एचआर भूमिका के सदस्यों को उदाहरण के लिए, सभी पंक्तियों को देखने में सक्षम होना चाहिए:

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

फिर आप जो भी करते हैं, वह सभी उपयोगकर्ताओं को दृश्य ( vwSomeTable) पर पढ़ने की अनुमति देता है (और लिखता है) , और मेज पर कोई अनुमति नहीं देता ( SomeTable)।

आप इसे इस तरह से परख सकते हैं:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... जो केवल उनकी पंक्ति (ओं) को वापस करना चाहिए। या:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... जो सभी पंक्तियों को वापस करेगा। ध्यान दें कि आपको इस परीक्षण को करने के लिए (प्रतिरूपण) अनुमतियों के रूप में निष्पादन की आवश्यकता होगी।

विचार उपयुक्त हैं, इसलिए नियमित उपयोगकर्ता भी ऐसा कर सकते हैं, जब तक कि पंक्ति उनकी Employeeपंक्ति से जुड़ी न हो :

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'

0

प्रमाण पत्र आधारित प्रमाणीकरण का उपयोग करना साझा एसक्यूएल खाते को लागू करने का "सही" तरीका है। लक्ष्य यह है कि इस तरह की चीज़ के लिए पासवर्ड का उपयोग समाप्त कर दें।

अपडेट करें:

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

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

संदर्भ: http://en.wikipedia.org/wiki/Public-key_infrastructure


क्या आप इस पर कुछ और जानकारी प्रदान कर सकते हैं? ऐसा लगता है कि यह मेरे मूल प्रश्न के इरादे के लिए रूढ़िवादी हो सकता है, लेकिन यह दिलचस्प है।
स्कॉट व्हिटलॉक

0

एक नए डेस्कटॉप सुरक्षा समाधान का निर्माण करते हुए, हमने वेब सेवा समाधान I solutionll के लिए वर्णन करने का प्रयास किया।

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

एक वेब सेवा जो एप्लिकेशन को चलाने के लिए सभी आवश्यक जानकारी प्रदान करती है, DB पासवर्ड, कनेक्शन स्ट्रिंग जानकारी, उपयोगकर्ता अनुमतियाँ, आदि ...

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

एक DLL डेस्कटॉप एप्लिकेशन से वेब-सेवा के लिए सभी संचार को संभालता है, जो केवल DLL में एक टोकन निर्माण के साथ सुलभ है।

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

इस तरह हम गिर गए यह सुरक्षा समस्या का एक अच्छा समाधान है जहाँ हम सबसे अधिक चिंतित हैं और कुछ डिज़ाइन खामियों से अच्छी तरह वाकिफ हैं। क्या इस कार्यान्वयन को लगभग समाप्त कर रहे हैं और अब तक हम परिणामों से खुश हैं।

संपादित करें: आप डिजिटल हस्ताक्षर और X.509 प्रमाणपत्र का उपयोग करके हैश विचार को बदल सकते हैं।


1
यह बहुत स्पष्ट लगता है जहां चकाचौंध सुरक्षा छेद है। आप जिस DLL की बात करते हैं वह क्लाइंट के सिस्टम पर है और आपके सर्वर कोड के लिए यह सत्यापित करने का कोई तरीका नहीं है कि यह DLL की वैध कॉपी या हैक किए गए / दुर्भावनापूर्ण / नकली एक से बात कर रहा है। आपने अभी बहुत कुछ जोड़े बिना, यदि कोई हो, तो अतिरिक्त सुरक्षा के लिए बहुत सारे काम किए। सभी दुर्भावनापूर्ण व्यक्ति को टोकन और एल्गोरिथ्म की आवश्यकता होती है, जो दोनों डीएलएल में हैं जो किसी को भी देखना चाहते हैं।
स्कॉट व्हाइटलॉक

@ScottWhitlock, हां, मैं सहमत हूं। हम DLL, और HTTPS पर जाने वाले ट्रैफ़िक पर ध्यान दे रहे हैं। हम उस पर सुधार करने की कोशिश कर रहे हैं, मैं वास्तव में इसे सुधारने के किसी भी इनपुट को पसंद करता हूं। लेकिन यह समाधान पहले से ही मौजूदा समस्याओं का एक बहुत हल करता है, जिसमें नेटवर्क फ़ाइलों में संग्रहीत सादे पाठ पासवर्ड शामिल हैं। इसके अलावा, webservice डेल्फी और क्लिपर (हार्बर) ग्राहकों को शामिल करते हुए हमारे द्वारा उपयोग की जाने वाली किसी भी ग्राहक भाषा द्वारा बहुत सारे कोड को अस्वीकार्य होने की अनुमति देता है!
विटोर अर्बेक्स

आपके सिस्टम में, उपयोगकर्ता लॉग इन करता है और संभवतः वेब सेवा द्वारा प्रमाणित होता है। HTTPS का उपयोग मानते हुए, क्या यह पर्याप्त नहीं है? आपको क्लाइंट सॉफ़्टवेयर पर भरोसा करने की ज़रूरत नहीं है, क्योंकि आप जानते हैं कि उपयोगकर्ता वह है जो वे कहते हैं कि वे हैं, और आप वेब सेवा को नियंत्रित करते हैं, इसलिए सुनिश्चित करें कि वेब सेवा केवल उस जानकारी को सौंपती है जो दिए गए उपयोगकर्ता को देखने के लिए अधिकृत है। यहां तक ​​कि अगर वे ग्राहक को उल्टा-सीधा लगाते हैं और खुद लिखते हैं, तो वे क्या नुकसान पहुंचा सकते हैं? केवल आपकी वेब सेवा DB पासवर्ड को जानती है, और यह सुरक्षित होना चाहिए।
स्कॉट व्हाइटलॉक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.