2016-08-29 11 views
6

मैं रूट के रूप में चल रहा है एक डेमॉन विकासशील रहा हूँ, लेकिन उपयोगकर्ता के साथ एक API कॉल करने के लिए की जरूरत है, मैं एपीआई कोड की जाँच की, यह getuid() का उपयोग करता है उपयोगकर्ता के लिए। जड़ उपयोगकर्ता setuid() द्वारा विशेषाधिकार चला जाता हैअस्थायी रूप से रूट से विशेषाधिकार कैसे छोड़ें?

हैं, तो यह जड़ को पुनर्स्थापित नहीं किया जा सकता है। यदि seteuid() को कॉल करना है, तो एपीआई अभी भी उपयोगकर्ता uid=0 के रूप में कुछ करेगा।

मैं बच्चे प्रक्रिया में एपीआई और setuid तक पहुँचने से पहले काम करना चाहिए कांटा लगता है, लेकिन फिर भी गाय अगर, यह बहुत अगर कई बार एपीआई बुला खर्च होंगे। प्रक्रिया पूल का उपयोग करने के अलावा समस्या को हल करना संभव है?

उत्तर

7

हाँ! एक भी प्रक्रिया बनाएँ उचित यूआईडी के साथ एपीआई फोन और एक पाइप, एक UNIX डोमेन सॉकेट या (साझा स्मृति) के माध्यम से कार्यक्रम के बाकी के साथ संवाद करने के लिए।

मेरा मतलब है, कांटा केवल एक बार और विशेषाधिकार प्राप्त उपयोगकर्ता किसी अन्य प्रक्रिया चालू रखने के। फिर आवश्यक होने पर और आवश्यकतानुसार दोनों के बीच संचार बनाएं। साथ ही, आप dbus का उपयोग करने पर विचार करना चाहेंगे क्योंकि यह systemd और आधुनिक लिनक्स पर पूरी तरह से एकीकृत करता है, आप चाहते हैं कि आपका डिमन दोनों के साथ अच्छी तरह से बातचीत करे।

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


किसी भी भारतीय दंड संहिता तंत्र है कि आप के लिए काम करता है।

+0

* डीबीस * को छोड़कर यह एक प्रभावी दृष्टिकोण है। यदि संभव हो तो एक [सॉकेट जोड़ी] (http://man7.org/linux/man-pages/man2/socketpair.2.html) का उपयोग करें, ताकि कनेक्शन तृतीय पक्षों से सुरक्षित हो। (मूल प्रक्रिया में अभी भी मूल विशेषाधिकार हैं, और हम नहीं चाहते हैं कि यह बाढ़ या फिक संदेशों से शोषक हो।) मैंने इसे व्यक्तिगत रूप से कुछ बार इस्तेमाल किया है, लेकिन अधिक महत्वपूर्ण बात यह है कि दूसरों को भी। सबसे व्यापक रूप से उपयोग किए जाने वाले उदाहरण शायद अपाचे [mod_cgid] (https://httpd.apache.org/docs/2.4/mod/mod_cgid.html) और [mod_fcgid] (https://httpd.apache.org/mod_fcgid/) मॉड्यूल हैं । –

+0

काम में मदद के लिए, एक और मशीन का उपयोग क्यों नहीं करते? क्या कोई समाधान है जो आपके से अधिक संसाधनों का उपभोग करता है?'Seteuid (2) 'के लिए एक सरल कॉल को' suid' उपयोगकर्ता आईडी और' असली 'उपयोगकर्ता आईडी के बीच आईडी स्विच करने की अनुमति देनी चाहिए। और यह यूनिक्स v7 से predates। –

+0

यदि एपीआई के बारे में कोई सुरक्षा चिंता है, तो मैं साझा स्मृति के माध्यम से संचार के खिलाफ सलाह दूंगा। साझा मेमोरी क्षेत्र में कचरा डेटा के माध्यम से विशेषाधिकार प्राप्त प्रक्रिया में अपरिभाषित व्यवहार को ट्रिगर करने वाले हमलावर का जोखिम पाइप के माध्यम से भेजे गए संदेश के मुकाबले कहीं अधिक गंभीर है। साझा मेमोरी क्षेत्र के साथ, आपके पास एक पाइप के साथ साझा क्षेत्र में दो प्रक्रियाओं की पूरी तरह से असीमित पहुंच है, आप निश्चित हो सकते हैं कि बच्चे को माता-पिता में प्राप्त होने के बाद डेटा नहीं बदलेगा। इस प्रकार माता-पिता वास्तव में इस पर अभिनय करने से पहले अवकाश पर डेटा को मान्य कर सकते हैं। – cmaster

-1
here से

:

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

-1

आप बचाया प्रक्रिया के यूआईडी में पूर्व प्रभावी uid स्टोर कर सकते हैं:

uid_t real = getuid(); 
uid_t privileged = geteuid(); 
setresuid(real, real, privileged); 
do_API_call(); // API's getuid() call now returns real 
setresuid(real, privileged, -1); // allowed, since saved==privileged 

वहाँ एक इसी setresgid बचाया GIDs उपयोग करने के लिए, भी है।


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


वास्तव में, आगे पढ़ने setreuid() पर पर्याप्त (और POSIX-conformant) होना चाहिए।setuid() का कहना है:

फोन करने वाले के प्रभावी यूआईडी जड़ है: असली यूआईडी, और बचाया सेट उपयोगकर्ता के आईडी भी सेट कर रहे हैं (अधिक सटीक अगर फोन करने वाले CAP_SETUID क्षमता है)।

और

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

लेकिन setreuid() के लिए ऐसा कोई कथन नहीं है।

0

एप्राइपिएट अनधिकृत सामान करने के लिए बस seteuid(2) पर कॉल करें। seteuid(2)वास्तविक (या सहेजे गए) उपयोगकर्ता आईडी (जो आपके मामले में SUID प्रोग्राम या root लॉन्च करता है) के बीच स्विच करने की अनुमति देता है और SUID उपयोगकर्ता आईडी (एक सूड प्रोग्राम से संबंधित है) तो वहां नहीं होना चाहिए बाद में विशेषाधिकार प्राप्त उपयोगकर्ता आईडी प्राप्त करने में समस्या (चूंकि सहेजी गई उपयोगकर्ता आईडी root है, तो आपको बार-बार स्विच करने के लिए कोई समस्या नहीं है)।

आप setuid(2) साथ UIDs बदलते हैं तो आपको सभी (प्रभावी, बचाया और वास्तविक UIDs) बदल देंगे और यह केवल जड़ उपयोगकर्ता के लिए अनुमति दी है (या एक कार्यक्रम setuid जड़ है, और कोई रास्ता नहीं है फिर वापस नहीं है)। अगले उदाहरण पर

देखो:

फ़ाइल pru49015.c:

$ pru49015 -i 37 
real uid=502; effective uid=0 
real uid=502; effective uid=37 
real uid=502; effective uid=502 

जब एक setuid-रूट कार्यक्रम

रूप में इस्तेमाल किया:

#include <stdio.h> 
#include <stdlib.h> 
#include <getopt.h> 

int main(int argc, char **argv) 
{ 
    int opt, suid = getuid(), /* this is the saved uid */ 
     uid = 0; 
    while ((opt = getopt(argc, argv, "i:")) != EOF) { 
     switch (opt) { 
     case 'i': uid = atoi(optarg); break; 
     } 
    } 
    /* execute this program with root privileges, like setuid root, for example */ 
    printf("real uid=%d; effective uid=%d\n", getuid(), geteuid()); 
    seteuid(uid); /* change to the non-privileged id configured */ 
    printf("real uid=%d; effective uid=%d\n", getuid(), geteuid()); 
    seteuid(suid); /* return back to saved uid */ 
    printf("real uid=%d; effective uid=%d\n", getuid(), geteuid()); 
} 

आप इस तरह एक आउटपुट मिल जाएगा

यदि आप इसे रूट के रूप में उपयोग करते हैं, तो आपको निम्न आउटपुट मिलेगा:

$ sudo pru$$ -i 37 
real uid=0; effective uid=0 
real uid=0; effective uid=37 
real uid=0; effective uid=0 

तंत्र है कि आप उपयोगकर्ता के बीच स्विच करने के लिए आप (इसे बचाया प्रयोक्ता आईडी कॉल) कर रहे हैं एक setuid- कार्यक्रम पर अनुमति दी जाती है और उपयोगकर्ता कार्यक्रम (बुलाया प्रभावी उपयोगकर्ता के लिए setuid चलाता है आईडी या suid उपयोगकर्ता) जितनी बार चाहें उतनी बार।

+0

मुझे लगता है कि यह ध्यान दिया जाना चाहिए कि यह दृष्टिकोण फोर्क-सेटुइड-संवाद दृष्टिकोण के रूप में लगभग सुरक्षित नहीं है: यदि कोई हमलावर आपकी प्रक्रिया को लेता है, तो उसे तत्काल रूट विशेषाधिकारों तक पहुंच मिलती है (एक अतिरिक्त कॉल के माध्यम से 'seteuid () ')। कांटा-सेटुइड-संवाद दृष्टिकोण के साथ, एक हमलावर को केवल निम्न विशेषाधिकारों तक पहुंच प्राप्त होती है, इसके लिए मूल रूप से रूट विशेषाधिकार प्राप्त करने के लिए मूल रूप से मूल प्रक्रिया को हैक करने की आवश्यकता होती है। मेरा मानना ​​है कि यही कारण है कि 'setuid() 'एक प्रक्रिया को उन्नत विशेषाधिकारों पर वापस जाने की अनुमति नहीं देता है। – cmaster

+0

@cmaster, हां, लेकिन अगर हमलावर के पास प्रक्रिया तक पहुंच है, तो यह अप्रतिबंधित स्थिति में जाने से पहले पहुंच प्राप्त कर सकता है ... और उसके बाद इसे विशेषाधिकार प्राप्त भी है। क्या आप मुझे बता रहे हैं कि आपका 'फोर्क-सीयूड-संवाद' दृष्टिकोण 'सेट्यूयूड (2)' सिस्कल से अधिक सुरक्षित है? क्या आपको 'सेट्यूयूड (2)' कॉल पर कोई भेद्यता मिली है? फिर यूनिक्स वी 7 के बाद से यह सभी यूनिक्स किस्मों में क्यों लागू किया गया है और किसी ने भी ध्यान नहीं दिया है? वैसे, यदि आप उन सभी कार्यक्रमों को लिखते हैं, तो आपको क्यों लगता है कि हमलावर सबसे कमजोर बिंदु चुनने वाला नहीं है (इस मामले में, यह * अधिभारित * विशेषाधिकार प्राप्त प्रक्रिया) –

+0

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

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