
Secure code execution
CodeJail अविश्वसनीय कोड को सुरक्षित सैंडबॉक्स में निष्पादित करने का प्रबंधन करता है। यह मुख्य रूप से Python निष्पादन के लिए डिज़ाइन किया गया है, लेकिन अन्य भाषाओं के लिए भी उपयोग किया जा सकता है।
सुरक्षा AppArmor के साथ लागू की जाती है। यदि आपका ऑपरेटिंग सिस्टम AppArmor का समर्थन नहीं करता है, या यदि AppArmor प्रोफ़ाइल सही ढंग से परिभाषित और कॉन्फ़िगर नहीं की गई है, तो CodeJail निष्पादन की सुरक्षा नहीं करेगा।
CodeJail को कॉन्फ़िगर करने योग्य बनाया गया है, और यदि आप इसे ठीक से इंस्टॉल करते हैं तो यह Python निष्पादन के लिए स्वतः-कॉन्फ़िगर हो जाएगा।
एक CodeJail सैंडबॉक्स में कई भाग होते हैं:
#) सैंडबॉक्स वातावरण। Python सेटअप के लिए, यह Python और संबंधित कोर पैकेज एक virtualenv के रूप में होंगे। इस दस्तावेज़ में इसे के रूप में दर्शाया गया है। यह केवल-पठनीय (read-only) है, और सैंडबॉक्स इंस्टेंशिएशन में साझा किया जाता है।
सैंडबॉक्स किया गया कोड भी OS लाइब्रेरीज़ तक उसी सीमा तक पहुँच रखता है जितनी AppArmor प्रोफ़ाइल अनुमति देती है।
#) सैंडबॉक्स निष्पादन निर्देशिका। यह /tmp/codejail-XXXXXXXX जैसी एक अस्थायी (ephemeral) केवल-पठनीय निर्देशिका है जिसमें प्रस्तुत कोड (./jailed_code), वैकल्पिक अतिरिक्त फ़ाइलें, और एक लिखने योग्य अस्थायी निर्देशिका (./tmp) होती है जिसे प्रस्तुत कोड स्क्रैच स्पेस के रूप में उपयोग कर सकता है।
प्रस्तुत कोड आम तौर पर वह कोड होता है जो छात्र द्वारा सर्वर पर परीक्षण के लिए प्रस्तुत किया जाता है, और अतिरिक्त फ़ाइलें आम तौर पर एक python_lib.zip होती हैं जिसमें ग्रेडिंग या उपयोगिता लाइब्रेरीज़ होती हैं।
चलाने के लिए, CodeJail को दो उपयोगकर्ता खातों की आवश्यकता होती है। एक खाता मुख्य खाता है जिसके अंतर्गत कोड चलता है, जिसके पास सैंडबॉक्स बनाने की पहुँच होती है। इसे <SANDBOX_CALLER> के रूप में संदर्भित किया जाएगा। दूसरा खाता वह खाता है जिसके अंतर्गत सैंडबॉक्स चलता है। यह आम तौर पर sandbox खाता होता है।
यह लाइब्रेरी वर्तमान में निम्नलिखित संस्करणों के साथ काम करने के लिए परीक्षण की गई है
Python:
Ubuntu:
(ध्यान दें कि सैंडबॉक्स के अंदर उपयोग किया जाने वाला Python संस्करण लाइब्रेरी के लिए उपयोग किए जाने वाले संस्करण से भिन्न हो सकता है।)
ये निर्देश बताते हैं कि अपने ऑपरेटिंग सिस्टम को कैसे कॉन्फ़िगर करें ताकि CodeJail Python कोड को सुरक्षित रूप से निष्पादित कर सके। हालाँकि, codejail.safe_exec.ALWAYS_BE_UNSAFE = True सेट करना और प्रस्तुत Python को सीधे मशीन पर बिना किसी सुरक्षा के निष्पादित करना भी संभव है। यह उन डेवलपर्स की मशीनों के लिए ठीक हो सकता है जो सुरक्षा के प्रति चिंतित नहीं हैं, और CodeJail के API के साथ एकीकरण का परीक्षण करने की अनुमति देता है। हालाँकि, यदि कोई इनपुट अविश्वसनीय स्रोतों से आ रहा है तो इसका उपयोग नहीं किया जाना चाहिए। इस विकल्प को प्रोडक्शन सिस्टम में उपयोग न करें।
Python निष्पादन को सुरक्षित करने के लिए, आप एक नया virtualenv बनाएंगे। इसका मतलब है कि आपके पास दो होंगे: आपके प्रोजेक्ट के लिए मुख्य virtualenv, और सैंडबॉक्स किए गए Python कोड के लिए नया।
नए virtualenv के लिए एक स्थान चुनें, इसे कहें। यदि आप इसे अपने मौजूदा virtualenv के ठीक बगल में रखते हैं, लेकिन -sandbox जोड़कर, तो यह स्वचालित रूप से पता लगाया और उपयोग किया जाएगा। इसलिए यदि आपका मौजूदा virtualenv /home/chris/ve/myproj में है, तो को /home/chris/ve/myproj-sandbox बनाएं।
LMS चलाने वाला उपयोगकर्ता <SANDBOX_CALLER> है, उदाहरण के लिए, आप अपनी डेव मशीन पर, या सर्वर पर www-data।
यहाँ अन्य विवरण जो आपके कॉन्फ़िगरेशन पर निर्भर करते हैं:
--copies का उपयोग करके नया virtualenv बनाएं, ताकि सीमित करने के लिए एक अलग Python निष्पादन योग्य हो::
$ sudo python3.12 -m venv --copies
डिफ़ॉल्ट रूप से, virtualenv केवल सिस्टम Python के खिलाफ सिमलिंक करेगा, और कुछ ऑपरेटिंग सिस्टम पर apparmor का डिफ़ॉल्ट कॉन्फ़िगरेशन उस पर confinement लागू होने से रोक सकता है।
(वैकल्पिक) यदि आपके पास विशेष पैकेज हैं जिन्हें आप अपने सैंडबॉक्स किए गए कोड के लिए उपलब्ध कराना चाहते हैं, तो सैंडबॉक्स virtual env को सक्रिय करके और उन्हें इंस्टॉल करने के लिए pip का उपयोग करके इंस्टॉल करें::
$ /bin/pip install -r requirements/sandbox.txt
एक सैंडबॉक्स उपयोगकर्ता जोड़ें::
$ sudo addgroup sandbox $ sudo adduser --disabled-login sandbox --ingroup sandbox
वेब सर्वर को सैंडबॉक्स किए गए Python को sandbox के रूप में चलाने दें। फ़ाइल /etc/sudoers.d/01-sandbox बनाएं::
$ sudo visudo -f /etc/sudoers.d/01-sandbox
<SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/bin/python <SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/usr/bin/find <SANDBOX_CALLER> ALL=(ALL) NOPASSWD:/usr/bin/pkill
(ध्यान दें कि find बाइनरी मनमाना कोड चला सकता है, इसलिए यह गैर-codejail उद्देश्यों के लिए एक सुरक्षित sudoers फ़ाइल नहीं है।)
एक AppArmor प्रोफ़ाइल संपादित करें। यह एक टेक्स्ट फ़ाइल है जो सैंडबॉक्स किए गए Python निष्पादन योग्य पर सीमाएँ निर्दिष्ट करती है। फ़ाइल /etc/apparmor.d में होनी चाहिए और निष्पादन योग्य के आधार पर नामित होनी चाहिए, जिसमें स्लैश को डॉट्स से बदला गया हो। उदाहरण के लिए, यदि आपका सैंडबॉक्स किया गया Python /home/chris/ve/myproj-sandbox/bin/python पर है, तो आपकी AppArmor प्रोफ़ाइल /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python होनी चाहिए।
यदि आपका CodeJail safe_exec का उपयोग करने के लिए ठीक से कॉन्फ़िगर किया गया है, तो अपने Python टर्मिनल पर इन कमांड्स को आज़माएं::
import codejail.jail_code
codejail.jail_code.configure('python', '<SANDENV>/bin/python', user='sandbox')
import codejail.safe_exec
jailed_globals = {}
codejail.safe_exec.safe_exec("output=open('/etc/passwd').read()", jailed_globals)
print(jailed_globals) # should be unreachable if codejail is working properly
इसे एक अपवाद (exception) के साथ विफल होना चाहिए।
यदि आपको अपने सैंडबॉक्स के virtualenv में स्थापित पैकेजों को बदलने की आवश्यकता है, तो आपको AppArmor को अक्षम करना होगा, क्योंकि आपके सैंडबॉक्स किए गए Python के पास अपनी site-packages निर्देशिका में फ़ाइलों को संशोधित करने के अधिकार नहीं हैं।
अपने सैंडबॉक्स के लिए AppArmor अक्षम करें::
$ sudo apt-get install apparmor-utils # if you haven't already $ sudo aa-complain /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
स्थापित पैकेजों को इंस्टॉल करें या अन्यथा बदलें::
$ pip install -r requirements/sandbox.txt
अपने सैंडबॉक्स के लिए AppArmor पुनः सक्षम करें::
$ sudo aa-enforce /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
परीक्षण चलाने के लिए, आपको मानक स्थापना चरणों का पालन करना होगा। फिर आपको निम्नलिखित पर्यावरण चर सेट करने होंगे::
$ export CODEJAIL_TEST_USER=<owner of sandbox (usually 'sandbox')>
$ export CODEJAIL_TEST_VENV=<SANDENV>
Makefile के साथ परीक्षण चलाएं::
$ make tests
यदि प्रॉक्सी मोड कॉन्फ़िगर नहीं किया गया है तो कई प्रॉक्सी परीक्षण छोड़ दिए जाते हैं।
CodeJail इतना सामान्य-उद्देश्यीय है कि इसका उपयोग विभिन्न परियोजनाओं में अविश्वसनीय कोड चलाने के लिए किया जा सकता है। यह दो परतें प्रदान करता है:
jail_code.py सबप्रोसेसों का सुरक्षित निष्पादन प्रदान करता है। यह प्रोग्राम को AppArmor द्वारा प्रबंधित सबप्रोसेस में चलाकर ऐसा करता है।
safe_exec.py Python निष्पादन का विशेष संचालन प्रदान करता है, Python के exec स्टेटमेंट के शब्दार्थ प्रदान करने के लिए jail_code का उपयोग करता है।
CodeJail प्रोग्रामों को AppArmor के अंतर्गत चलाता है। AppArmor एक OS-प्रदत्त सुविधा है जो प्रोग्रामों द्वारा एक्सेस किए जा सकने वाले संसाधनों को सीमित करती है। संसाधनों तक सीमित पहुँच के साथ Python कोड चलाने के लिए, हम एक नया virtualenv बनाते हैं, फिर उस Python निष्पादन योग्य का नाम AppArmor प्रोफ़ाइल में देते हैं, और उस प्रोफ़ाइल में संसाधनों को प्रतिबंधित करते हैं। CodeJail प्रदान किए गए Python प्रोग्राम को उस निष्पादन योग्य के साथ निष्पादित करेगा, और AppArmor स्वचालित रूप से उसके द्वारा एक्सेस किए जा सकने वाले संसाधनों को सीमित कर देगा। CodeJail प्रक्रिया के लिए उपलब्ध CPU समय और/या मेमोरी की मात्रा को सीमित करने के लिए setrlimit का भी उपयोग करता है।
codejail.jail_code चलाने के लिए एक प्रोग्राम, उसके वातावरण में कॉपी करने के लिए फ़ाइलें, कमांड-लाइन तर्क और एक stdin स्ट्रीम लेता है। यह एक अस्थायी निर्देशिका बनाता है, आवश्यक फ़ाइलें बनाता या कॉपी करता है, कोड चलाने के लिए एक सबप्रोसेस शुरू करता है, और प्रक्रिया का आउटपुट और एग्ज़िट स्थिति लौटाता है।
codejail.safe_exec Python के exec स्टेटमेंट का अनुकरण करता है। यह Python कोड का एक हिस्सा लेता है, और उसे jail_code का उपयोग करके चलाता है, साइड-इफेक्ट के रूप में globals डिक्शनरी को संशोधित करता है। safe_exec ऐसा globals को सबप्रोसेस में और बाहर JSON के रूप में क्रमबद्ध (serialize) करके करता है।
यदि codejail या AppArmor ठीक से कॉन्फ़िगर नहीं किया गया है, तो codejail डिफ़ॉल्ट रूप से कोड को असुरक्षित रूप से (बिना सैंडबॉक्सिंग के) चला सकता है। यह डिफ़ॉल्ट रूप से सुरक्षित नहीं है। codejail को एकीकृत करने वाली परियोजनाओं को एक रनटाइम परीक्षण सूट शामिल करने पर विचार करना चाहिए जो अविश्वसनीय इनपुट स्वीकार करने से पहले स्टार्टअप पर उचित confinement की जाँच करता है।
सैंडबॉक्स अलगाव AppArmor confinement के माध्यम से प्राप्त किया जाता है। Codejail इसे सुविधाजनक बनाता है, लेकिन AppArmor के उपयोग के बिना निष्पादन को अलग नहीं कर सकता।
संसाधन सीमाएँ केवल उन तंत्रों का उपयोग करके प्रतिबंधित की जा सकती हैं जो Linux का rlimit उपलब्ध कराता है। कुछ उल्लेखनीय कमियाँ:
FSIZE किसी एक फ़ाइल के आकार को सीमित कर सकता है जिसे एक प्रक्रिया बना सकती है, और एक समय में उसके द्वारा खोली गई फ़ाइलों की संख्या को सीमित कर सकता है, यह लिखी गई फ़ाइलों की कुल संख्या को सीमित नहीं कर सकता, और इसलिए सभी फ़ाइलों में लिखे गए बाइट्स की कुल संख्या को सीमित नहीं कर सकता। एक आंशिक शमन अधिकतम निष्पादन समय को बाधित करना है। (सैंडबॉक्स में लिखी गई सभी फ़ाइलें निष्पादन के अंत में हटा दी जाएंगी, किसी भी स्थिति में।)NPROC सीमा वर्तमान प्रक्रिया की नई थ्रेड्स और प्रक्रियाएँ बनाने की क्षमता को प्रतिबंधित करती है, लेकिन उपयोग गणना (कितनी प्रक्रियाएँ पहले से मौजूद हैं) समान UID वाली सभी प्रक्रियाओं का योग है, यहाँ तक कि उसी होस्ट पर अन्य कंटेनरों में भी जहाँ UID एक अलग उपयोगकर्ता नाम से मैप किया जा सकता है। यह बाधा rlimits को लागू करने के तरीके के कारण ऐप उपयोगकर्ता पर भी लागू होती है। भले ही UIDs को इस तरह चुना गया हो कि वे होस्ट पर अन्य सॉफ़्टवेयर द्वारा उपयोग नहीं किए जाते हैं, एक ही होस्ट पर कई codejail सैंडबॉक्स प्रक्रियाएँ इस उपयोग पूल को साझा करेंगी और एक-दूसरे की प्रक्रियाएँ बनाने की क्षमता को कम कर सकती हैं। इस स्थिति में, एक समय में एक ही अनुरोध लेने वाले एकल codejail इंस्टेंस के लिए आवश्यक से NPROC को अधिक सेट करने की आवश्यकता होगी।सैंडबॉक्स में एक-दूसरे से मजबूत अलगाव नहीं होता है। उचित कॉन्फ़िगरेशन के तहत, अविश्वसनीय कोड को अन्य सक्रिय रूप से चल रहे कोड निष्पादनों की खोज करने में सक्षम नहीं होना चाहिए, लेकिन यदि इस धारणा का उल्लंघन किया जाता है तो एक सैंडबॉक्स सैद्धांतिक रूप से दूसरे के साथ हस्तक्षेप कर सकता है।
कृपया सुरक्षा मुद्दों को सार्वजनिक रूप से रिपोर्ट न करें। कृपया [email protected] पर ईमेल करें।
नमूना प्रोफ़ाइल apparmor-profiles/ में देखें। प्रोफ़ाइल को आपके सैंडबॉक्स स्थान से मेल खाने के लिए अनुकूलित किया जाना चाहिए।
प्रोफ़ाइलों को पार्स करें::
$ sudo apparmor_parser --replace --warn=all --warn=no-debug-cache --Werror <APPARMOR_FILE>
अपने प्रोजेक्ट के मुख्य virtualenv को फिर से सक्रिय करें।
rlimits सेट करने के लिए PAM का उपयोग अक्षम करें::
sed -i '/pam_limits.so/d' /etc/pam.d/sudo