सेटियड बिट का ठीक से उपयोग करना


45

मेरे पास एक ऐसी प्रक्रिया है जो सामान्य उपयोगकर्ता द्वारा चलाने पर रूट विशेषाधिकार की आवश्यकता होती है। जाहिरा तौर पर मैं इसे पूरा करने के लिए "सेट्युड बिट" का उपयोग कर सकता हूं। POSIX सिस्टम पर ऐसा करने का उचित तरीका क्या है?

इसके अलावा, मैं एक स्क्रिप्ट के साथ ऐसा कैसे कर सकता हूं जो एक दुभाषिया (बैश, पर्ल, अजगर, php, आदि) का उपयोग करता है?

जवाबों:


53

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

कुछ सामान्य उपयोगिताओं, जैसे कि passwd, स्वामित्व वाली जड़ें हैं और इस तरह से आवश्यकता से बाहर कॉन्फ़िगर किया गया है ( passwdएक्सेस करने की आवश्यकता है /etc/shadowजिसे केवल रूट द्वारा पढ़ा जा सकता है)।

ऐसा करते समय सबसे अच्छी रणनीति यह है कि आपको जो कुछ भी करने की ज़रूरत है वह सुपरसुअर के रूप में तुरंत करें फिर कम विशेषाधिकार ताकि बग को चलाने के दौरान बग या दुरुपयोग की संभावना कम हो। ऐसा करने के लिए, आप प्रक्रिया के प्रभावी यूआईडी को उसके वास्तविक यूआईडी पर सेट करते हैं । POSIX C में:

#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void report (uid_t real) {
    printf (
        "Real UID: %d Effective UID: %d\n",
        real,
        geteuid()
    );
}

int main (void) {
    uid_t real = getuid();
    report(real);
    seteuid(real);
    report(real);
    return 0;
}

प्रासंगिक कार्य, जिनमें अधिकांश उच्च स्तरीय भाषाओं में एक समान होना चाहिए, यदि वे आमतौर पर POSIX सिस्टम पर उपयोग किए जाते हैं:

  • getuid(): वास्तविक यूआईडी प्राप्त करें ।
  • geteuid(): प्रभावी यूआईडी प्राप्त करें ।
  • seteuid(): प्रभावी यूआईडी सेट करें ।

आप वास्तविक यूआईडी के लिए पिछले एक अनुचित के साथ कुछ भी नहीं कर सकते हैं सिवाय इसके कि अभी तक निष्पादन योग्य पर सेट बिट को सेट किया गया था । तो यह कोशिश करने के लिए, संकलन करें gcc test.c -o testuid। फिर आपको विशेषाधिकारों के साथ:

chown root testuid
chmod u+s testuid

अंतिम सेटूइट बिट सेट करता है। यदि आप अब ./testuidएक सामान्य उपयोगकर्ता के रूप में चलते हैं, तो आप प्रक्रिया को डिफ़ॉल्ट रूप से प्रभावी uid 0, रूट के साथ देखेंगे।

लिपियों के बारे में क्या?

यह एक प्लेटफ़ॉर्म से दूसरे प्लेटफ़ॉर्म पर भिन्न होता है , लेकिन लिनक्स पर, जिन चीज़ों के लिए एक इंटरप्रेटर की आवश्यकता होती है, जिसमें बायटेकोड भी शामिल है, जब तक कि यह दुभाषिया पर सेट न हो जाए (जो बहुत बेवकूफ होगा)। यहां एक सरल पर्ल स्क्रिप्ट दी गई है जो ऊपर दिए गए C कोड की नकल करती है:

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

print "Real UID: $< Effective UID: $>\n";
$> = $<; # Not an ASCII art greedy face, but genuine perl...
print "Real UID: $< Effective UID: $>\n"; 

यह सच है * nixy जड़ें, पर्ल प्रभावी uid ( $>) और असली uid ( $<) के लिए विशेष चर में निर्माण किया है । लेकिन अगर आप एक ही प्रयास करते हैं chownऔर chmodसंकलित (सी, पिछले उदाहरण से) निष्पादन योग्य के साथ उपयोग किया जाता है, तो इससे कोई फर्क नहीं पड़ेगा। स्क्रिप्ट को विशेषाधिकार नहीं मिल सकते।

इसका उत्तर स्क्रिप्ट को निष्पादित करने के लिए एक सेतु द्विआधारी का उपयोग करना है:

#include <stdio.h>
#include <unistd.h> 

int main (int argc, char *argv[]) {
    if (argc < 2) {
        puts("Path to perl script required.");
        return 1;
    }
    const char *perl = "perl";
    argv[0] = (char*)perl;
    return execv("/usr/bin/perl", argv);
}

यह संकलन करें gcc --std=c99 whatever.c -o perlsuid, फिर chown root perlsuid && chmod u+s perlsuid। अब आप किसी भी पर्ल स्क्रिप्ट को 0 के प्रभावी यूआईडी के साथ निष्पादित कर सकते हैं , भले ही इसका मालिक कोई भी हो।

इसी तरह की रणनीति php, अजगर, आदि के साथ काम करेगी लेकिन ...

# Think hard, very important:
>_< # Genuine ASCII art "Oh tish!" face

कृपया ध्यान दें कि इस तरह की चीज़ को आस-पास न छोड़ें सबसे अधिक संभावना है, आप वास्तव में स्क्रिप्ट के नाम को एक पूर्ण पथ के रूप में संकलित करना चाहते हैं , अर्थात, सभी कोड को इसके main()साथ बदलें :

    const char *args[] = { "perl", "/opt/suid_scripts/whatever.pl" }
    return execv("/usr/bin/perl", (char * const*)args);

उन्हें सुनिश्चित करें /opt/suid_scriptsऔर इसमें सब कुछ केवल गैर-रूट उपयोगकर्ताओं के लिए पढ़ा जाता है। अन्यथा, किसी के लिए कुछ भी स्वैप कर सकता था whatever.pl

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

तो इसके बजाय मुझे क्या करना चाहिए?

एक गैर-रूट उपयोगकर्ता को स्क्रिप्ट चलाने की अनुमति देने का एक सुरक्षित तरीका है कि एक sudo नियम जोड़ना और उपयोगकर्ता को चलाना है sudo /path/to/script। सूडो अधिकांश पर्यावरण चर को स्ट्रिप्स करते हैं, और व्यवस्थापक को यह भी चुनने की अनुमति देते हैं कि कौन कमांड को चला सकता है और किन तर्कों के साथ। देखें कि पासवर्ड के बिना रूट के रूप में एक विशिष्ट प्रोग्राम कैसे चलाया जाए? एक उदाहरण के लिए।


1
कई गोले अलग तरह से व्यवहार करेंगे यदि एक -privilegedखोल के रूप में कहा जाता है और, यदि एक जिम्मेदार स्क्रिप्ट से कहा जाता है, तो भी सुरक्षित रूप से suid rootउस तरह से लागू किया जा सकता है । मुझे डर है कि एक जिम्मेदार स्क्रिप्ट की धारणा वास्तविक दुनिया में एक विडंबना है। वैसे भी, यह संभवतः उल्लेख के लायक है कि सभी प्रकार के लेखन से बचना कितना महत्वपूर्ण है यदि संभव हो तो अनुमतियाँ ऊपर उठाई जाएं ...
mikeserv

@ माइकर्स मैं " -privilegedशेल" और "जिम्मेदार स्क्रिप्ट" की अवधारणाओं से परिचित नहीं हूं । क्या आप गोले के बारे में एक और जवाब देना चाहते हैं? मैं आपको निश्चित रूप से टिक का वादा नहीं कर सकता;) ऐसा करने के लिए कई अच्छे कारण नहीं हैं - sudoयदि संभव हो तो एक बहुत ही बेहतर विकल्प है - मैंने इसे php में सिस्टम पासवर्ड प्रमाणीकरण के बारे में एक प्रारंभिक प्रश्न से उत्पन्न एक सामान्य उत्तर के रूप में लिखा था। ।
गोल्डीलॉक्स

1
- मैं नहीं है वास्तव में ऐसा करना चाहते जिम्मेदार लिपियों हैं वास्तव में कड़ी मेहनत , मुझे परे शायद -। लेकिन मुझे कहना होगा कि मैं आपके विश्लेषण से असहमत हूं sudo- मैं इस बात sudoको मनोवैज्ञानिक मानता हूं कि यह दिखावा नहीं है root। तुम भी खोल दस्ताने अपने में डाल सकते हैं sudoerssuस्क्रिप्टिंग उद्देश्यों के लिए मेरी राय में बेहतर है, हालांकि sudoलाइव अनुप्रयोगों के लिए अच्छा है। लेकिन न तो एक के साथ एक स्क्रिप्ट के रूप में स्पष्ट रूप में है #!/bin/ksh -pbangline या जो कुछ भी suid kshमें $PATHहै।
15

हालांकि यह उत्तर प्रश्न को संबोधित करता है, लेकिन सेतुकृत लिपियाँ अपने आप को एक स्थानीय विशेषाधिकार वृद्धि भेद्यता के लिए खोलने का एक नुस्खा है। एक कारण है कि लिपियों को आसानी से निर्धारित नहीं किया जा सकता है। यहाँ सही उत्तर सूडो है।
mdadm

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

11

हाँ आप कर सकते हैं, लेकिन यह शायद एक बहुत बुरा विचार है । आमतौर पर, आप सीधे अपने निष्पादन योग्य पर SUID बिट सेट नहीं करेंगे, लेकिन इसे निष्पादित करने के लिए एक sudo (8) या su (1) का उपयोग करें (और इसे निष्पादित कर सकते हैं जो सीमित करें)

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

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

उदाहरण के लिए, आप उन उपयोगकर्ताओं को अनुमति दे सकते हैं जो केवल कुछ फ़ाइल को संपादक के साथ संपादित करते हैं। लेकिन संपादक बाहरी सहायकों को निलंबित करने या निलंबित करने की अनुमति देता है, इस प्रकार उपयोगकर्ताओं को अपनी इच्छा के अनुसार रूट शेल देता है। या आप शेल स्क्रिप्ट्स को निष्पादित कर रहे होंगे जो आपको बहुत सुरक्षा-तंग दिखती हैं, लेकिन उपयोगकर्ता इसे संशोधित $ IFS या अन्य पर्यावरण चर के साथ चला सकते हैं जो इसे पूरी तरह से बदल रहा है। या यह PHP स्क्रिप्ट हो सकती है जिसे "ls" निष्पादित करना चाहिए, लेकिन उपयोगकर्ता इसे $ PATH संशोधित करके चलाता है और इस प्रकार यह एक शेल चलाता है जिसे वह "ls" नाम देता है। या दर्जनों अन्य सुरक्षा समस्याएं।

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

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


1
seconded। POSIX प्रोग्रामर की श्रृंखला में सुरक्षित मंगलाचरण उदाहरण देखें man sh- और यहां तक ​​कि ऐसा करने में विफल रहता है command -p env -i ...। यह सब करने के बाद बहुत मुश्किल है। फिर भी, अगर इसे सही तरीके से किया जाता है , तो स्पष्ट उद्देश्यों के लिए, इसका suidउपयोग करने की तुलना में सक्षम दुभाषिया के लिए बेहतर हो सकता है - suया sudoतो किसी का व्यवहार हमेशा स्क्रिप्ट के नियंत्रण से बाहर होगा (हालांकि suवक्र गेंदों को फेंकने की संभावना कम है क्योंकि यह झुकता है थोड़ा कम पागल होना) । पूरे पैकेज को बंडल करना एकमात्र निश्चित शर्त है - यह केवल बेहतर था सुनिश्चित करें कि यह सब है।
मोकेसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.