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
। सूडो अधिकांश पर्यावरण चर को स्ट्रिप्स करते हैं, और व्यवस्थापक को यह भी चुनने की अनुमति देते हैं कि कौन कमांड को चला सकता है और किन तर्कों के साथ। देखें कि पासवर्ड के बिना रूट के रूप में एक विशिष्ट प्रोग्राम कैसे चलाया जाए? एक उदाहरण के लिए।
-privileged
खोल के रूप में कहा जाता है और, यदि एक जिम्मेदार स्क्रिप्ट से कहा जाता है, तो भी सुरक्षित रूप सेsuid root
उस तरह से लागू किया जा सकता है । मुझे डर है कि एक जिम्मेदार स्क्रिप्ट की धारणा वास्तविक दुनिया में एक विडंबना है। वैसे भी, यह संभवतः उल्लेख के लायक है कि सभी प्रकार के लेखन से बचना कितना महत्वपूर्ण है यदि संभव हो तो अनुमतियाँ ऊपर उठाई जाएं ...