2012-10-24 6 views
6

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

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

+6

अच्छे या बुरे विचार के बावजूद, यह काम नहीं करेगा। यहां तक ​​कि [एएसएलआर] के बिना भी (http://en.wikipedia.org/wiki/Address_space_layout_randomization), आपको हमेशा भाग्यशाली होना होगा कि सूचक हमेशा एक ही पता हो। एएसएलआर के साथ, आप बहुत अधिक गारंटी देते हैं कि यह कभी नहीं होगा। –

+0

नहीं। एन्क्रिप्शन के बिना नेटवर्क पर कुछ भी सुरक्षित नहीं है। कुछ प्रकार के वादे के बिना कॉलिंग फ़ंक्शंस यह काम करेगा (क्योंकि पॉइंटर * आपको * ले जाएगा) सुरक्षित नहीं है। प्रोटोकॉल का प्रयोग करें। – Incognito

+1

चिंता न करें, मैं ऐसा करने वाला नहीं हूं, मैं बस सोच रहा हूं कि यह संभव है और किस परिस्थिति में। – Jack

उत्तर

6

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

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

मैं उच्च स्तर की कमांड संरचना या सार आरपीसी ढांचे के पक्ष में पूरी तरह से निम्न स्तर के आरपीसी से बचूंगा, लेकिन यदि आप वास्तव में ऐसा करना चाहते हैं, तो फ़ंक्शन नामों और उपयोग को पास करने के लिए थोड़ा सुरक्षित दृष्टिकोण होगा dlsym या उन्हें देखने के लिए समकक्ष। यदि प्रतीकों पुस्तकालयों की बजाय मुख्य कार्यक्रम बाइनरी में रहते हैं, तो आपके प्लेटफ़ॉर्म के आधार पर आपको -rdynamic (GCC) या dlsym पर उपलब्ध कराने के लिए एक समान विकल्प की आवश्यकता हो सकती है। libffi यह सारण करने के लिए भी एक उपयोगी उपकरण हो सकता है।

इसके अलावा, अगर आप dlsym या libffi पर निर्भर करता है से बचना चाहते हैं, आप अपने खुद के "प्रतीक तालिका" हार्ड-कोड static const रैखिक मेज या हैश तालिका मानचित्रण प्रतीक नाम के रूप में द्विआधारी में कार्य करने के संकेत दिए गए रख सकता है। इस उद्देश्य के लिए ईएलएफ में उपयोग किया गया हैश टेबल प्रारूप समझने और कार्यान्वित करने के लिए बहुत आसान है, इसलिए मैं उस पर आपके कार्यान्वयन के आधार पर विचार कर सकता हूं।

1

यह एक सूचक है?

क्या यह स्थिर प्रोग्राम मेमोरी के टुकड़े के लिए सूचक है? यदि ऐसा है, तो यह न भूलें कि यह एक पता है, ऑफसेट नहीं, इसलिए आपको पहले दोनों के बीच में कनवर्ट करना होगा।

दूसरा, यदि यह स्थैतिक स्मृति का एक टुकड़ा नहीं है (यानी: रन टाइम के विपरीत निर्माण समय पर बनाए गए स्थिर आवंटित सरणी) यह वास्तव में संभव नहीं है।

अंत में, आप कोड के दो टुकड़े कैसे सुनिश्चित कर रहे हैं? क्या दोनों द्विआधारी समान समान हैं (उदाहरण: diff -a binary1 binary2)। यहां तक ​​कि यदि वे प्रत्येक मशीन पर वर्चुअल मेमोरी प्रबंधन के आधार पर थोड़ा-समान हैं, तो पूरे प्रोग्राम का प्रोग्राम मेमोरी सेगमेंट एक पृष्ठ में मौजूद नहीं हो सकता है, या एकाधिक सिस्टम में संरेखण प्रत्येक सिस्टम के लिए अलग हो सकता है।

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

1

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

फिर भी, "समान बाइनरी कोड" को स्थिर लिंकिंग द्वारा सर्वोत्तम आश्वासन दिया जाता है - यदि विभिन्न साझा वस्तुओं/पुस्तकालयों को लोड किया जाता है, या वे अलग-अलग क्रम में लोड होते हैं (शायद गतिशील लोडिंग के कारण - dlopen - कॉन्फ़िगरेशन में विभिन्न ऑर्डरिंग द्वारा संचालित फाइलें या कमांड लाइन तर्क इत्यादि) आप शायद भरवां हैं।

1

मुझे किसी भी प्रकार का आरपीसी नहीं पता है जो आपको नेटवर्क पर एक सूचक भेजने देगा (कम से कम int पर कास्टिंग करने जैसा कुछ भी नहीं)। यदि आप भेजने के अंत में int में कनवर्ट करते हैं, और इसे दूर तक एक पॉइंटर में कनवर्ट करते हैं, तो आप किसी भी अन्य मनमानी int को पॉइंटर में कनवर्ट करने के समान ही प्राप्त करते हैं: अपरिभाषित व्यवहार यदि आप कभी इसे अस्वीकार करने का प्रयास करते हैं।

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

1

नेटवर्क पर एक सूचक भेजना आम तौर पर असुरक्षित है। दो मुख्य कारण हैं:

  • विश्वसनीयता: डेटा/समारोह सूचक कार्यक्रम के विभिन्न स्थान या उसके पुस्तकालयों या गतिशील रूप से आवंटित की वजह से एक ही इकाई (डेटा संरचना या कार्य) एक और मशीन पर को इंगित नहीं हो सकता है स्मृति में वस्तुओं। स्थानांतरित करने योग्य कोड + एएसएलआर आपके डिजाइन को तोड़ सकता है। कम से कम, यदि आप एक स्थिर आवंटित ऑब्जेक्ट या फ़ंक्शन को इंगित करना चाहते हैं तो आपको अपना ऑफ़सेट w.r.t. भेजना चाहिए। छवि आधार यदि आपका प्लेटफॉर्म विंडोज है या आप जो भी ओएस पर समान कुछ करते हैं।
  • सुरक्षा: यदि आपका नेटवर्क खुला है और एक हैकर (या वे आपके नेटवर्क में टूट गए हैं) हैं, तो वे आपकी पहली मशीन का प्रतिरूपण कर सकते हैं और दूसरी मशीन को या तो लटका या क्रैश कर सकते हैं, जिससे सेवा अस्वीकार हो जाती है, या निष्पादित हो जाता है मनमानी कोड और संवेदनशील जानकारी तक पहुंच प्राप्त करें या इसके साथ छेड़छाड़ करें या मशीन को हाइजैक करें और स्पैम भेजने या अन्य कंप्यूटरों पर हमला करने के लिए इसे एक बुरा बॉट में बदल दें। बेशक, यहां उपाय और प्रतिवाद हैं, लेकिन ...

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

1

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

हालांकि मैं आपको एक परिदृश्य प्रदान कर सकता हूं जहां मैं 99 वर्ष का हूं।99% यकीन है कि यह बिना किसी समस्या के काम करेगा:

  • विंडोज
  • 32 बिट प्रक्रिया
  • समारोह एक मॉड्यूल स्थानांतरण जानकारी
  • प्रश्न में मॉड्यूल नहीं है में स्थित है पहले से ही भरा हुआ है & ग्राहक के पक्ष
  • प्रश्न में मॉड्यूल दोनों पक्षों पर 100% समान है पर प्रारंभ
  • एक संकलक है कि बहुत पागल सामान नहीं करता है (उदाहरण के लिए MSVC और जीसीसी दोनों ठीक होना चाहिए)

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

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

उपरोक्त में से अधिकांश केवल यह सुनिश्चित करता है कि फ़ंक्शन दोनों तरफ एक ही पता होगा। एकमात्र शेष प्रश्न - कम से कम मैं सोच सकता हूं - है: क्या यह एक पॉइंटर के माध्यम से एक फ़ंक्शन को कॉल करना सुरक्षित है जिसे हमने नेटवर्क से प्राप्त कुछ बाइट्स पर memcpy-ing द्वारा प्रारंभ किया है, मानते हैं कि बाइट-पैटर्न वही है कि अगर हम वांछित कार्य का पता ले चुके हैं तो हम मिलेंगे? यह निश्चित रूप से ऐसा कुछ है जो सी ++ मानक गारंटी नहीं देता है, लेकिन मुझे वर्तमान वास्तविक दुनिया के किसी भी वास्तविक दुनिया की समस्याओं की उम्मीद नहीं है।

कहा जा रहा है कि, मैं ऐसा करने की अनुशंसा करता हूं, ऐसी स्थितियों को छोड़कर जहां सुरक्षा और मजबूती वास्तव में महत्वपूर्ण नहीं है।

संबंधित मुद्दे