2014-12-12 11 views
8

दोनों system() और execve() एक कार्यक्रम के अंदर एक और आदेश पर अमल करने के लिए इस्तेमाल किया जा सकता है। सेट-यूआईडी कार्यक्रमों में क्यों, system() खतरनाक है, जबकि execve() सुरक्षित है? अलग अलग तरीकों सेप्रणाली() execve बनाम()

उत्तर

9

system() और execve() काम करते हैं। system() हमेशा शैल का आह्वान करेगा और यह खोल कमांड को एक अलग प्रक्रिया के रूप में निष्पादित करेगा (यही कारण है कि आप system() का उपयोग करते समय कमांड लाइन में वाइल्डकार्ड और अन्य खोल सुविधाओं का उपयोग कर सकते हैं)।

execve() (और exec() परिवार में अन्य फ़ंक्शंस) वर्तमान प्रक्रिया को सीधे उत्पन्न होने वाले व्यक्ति के साथ बदलता है (विफलता के मामले में execve() फ़ंक्शन वापस नहीं आता है)। वास्तव में system() कार्यान्वयन को fork(), execve() और wait() कॉल का अनुक्रम करने के लिए कॉल का अनुक्रम उपयोग करना चाहिए।

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

+0

तो execve() का उपयोग करते समय .. आप उल्लेख करते हैं कि यह वर्तमान प्रक्रिया को प्रतिस्थापित करता है .. क्या प्रक्रिया निर्धारित हो जाएगी? – Jake

+0

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

12

system तर्क के रूप में भेजे गए आदेश को निष्पादित करने के लिए खोल (sh) को कॉल करेगा। system के साथ समस्या क्योंकि शेल व्यवहार उस उपयोगकर्ता पर निर्भर करता है जो कमांड चलाता है। एक छोटा सा उदाहरण:

#include <stdio.h> 

int main(void) { 
    if (system ("ls") != 0) 
     printf("Error!"); 
    return 0; 
} 

तब:: अब

$ cat > ls 
#!/bin/sh 

/bin/sh 

$ chmod +x ls 

:

$ gcc test.c -o test 

$ sudo chown root:root test 

$ sudo chmod +s test 

$ ls -l test 
-rwsr-sr-x 1 root root 6900 Dec 12 17:53 test 

एक स्क्रिप्ट अपने वर्तमान निर्देशिका में ls बुलाया बनाना

एक फ़ाइल test.c बनाना

$ PATH=. ./test 
# /usr/bin/id 
uid=1000(cuonglm) gid=1000(cuonglm) euid=0(root) egid=0(root) groups=0(root), 
24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),105(scanner), 
110(bluetooth),111(netdev),999(docker),1000(cuonglm) 
# /usr/bin/whoami 
root 

ओह, आपको रूट विशेषाधिकारों के साथ एक खोल मिला है।

execve एक खोल फोन नहीं करता है। यह उस कार्यक्रम को निष्पादित करता है जो इसे पहले तर्क के रूप में पास करता है। कार्यक्रम shebang लाइन के साथ बाइनरी निष्पादन योग्य या स्क्रिप्ट प्रारंभ होना चाहिए।

+0

यह नहीं कह रहा कि 'सिस्टम()' समस्याओं के बिना है लेकिन बाइनरी निष्पादन योग्य में पूर्ण पथ का उपयोग करके उपर्युक्त हल नहीं किया जाएगा? – Bratchley

+1

@ जोएल डेविस, नहीं, आपको कम से कम पूरे वातावरण को साफ़ करने की आवश्यकता होगी, कुछ envvars (पैथ, HOME ...) को सैने डिफ़ॉल्ट मान दें, यदि आवश्यक हो तो sanitizing (TERM, DISPLAY, LANG) के बाद कुछ env vars को सुरक्षित रखें। ..) सुनिश्चित करें कि एफडीएस 0, 1, 2 खुले हैं ... मूल रूप से जो सुडो करता है वह करो। फिर भी, मैं वहां नहीं जाऊंगा। विशेषाधिकार वृद्धि संदर्भ में एक खोल का आह्वान न करें अगर इसे टाला जा सके। ध्यान दें कि 'एलएस' अपने पर्यावरण के साथ फैंसी चीजें कर सकता है, इसलिए बिना सिस्टम() 'के, आपको शायद पर्यावरण को स्वच्छ करना चाहिए। सेटयूड्स का उपयोग करते समय आप रूट के रूप में क्या किया जाता है कम करना चाहते हैं (आमतौर पर कमांड निष्पादित नहीं करते हैं)। –

+3

@ जोएल डेविस: नहीं, आपको अभी भी समस्या है, भले ही आप पूर्ण पथ का उपयोग करें। यदि आप '/ bin/ls' का उपयोग करते हैं, तो उपयोगकर्ता '/' 'iFS' में'/'जोड़ सकता है, जिससे खोल विभाजित'/bin/ls' 'bin' और' ls' हो जाता है। अब, वर्तमान निर्देशिका में 'bin' नामक निष्पादन योग्य मेरे उत्तर में 'ls' जैसा ही काम कर सकता है। – cuonglm

0

अलावा system() साथ metioned सुरक्षा के मुद्दों से, पैदा की प्रक्रिया मुख्य कार्यक्रम के पर्यावरण इनहेरिट करती है। suid का उपयोग करते समय यह बहुत ही समस्याग्रस्त हो सकता है, उदाहरण के लिए जब कॉलिंग प्रक्रिया LD_LIBRARY_PATH-पर्यावरण चर सेट करती है।

exec() के साथ -फैमिली कॉलिंग प्रोग्राम exec() पर कॉल करने से पहले कॉल किए गए प्रोग्राम के लिए पर्यावरण की आवश्यकता (और सुरक्षित) के लिए पर्यावरण को सेट कर सकता है।

और हां खोल system() से बुलाया की सुरक्षा के मुद्दों में ही हो सकता है।

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