Setuid bitini doğru kullanmak


45

Normal bir kullanıcı tarafından çalıştırıldığında root yetkilerine ihtiyaç duyan bir süreç var. Görünüşe göre bunu yapmak için "setuid bit" i kullanabilirim. POSIX sisteminde bunu yapmanın doğru yolu nedir?

Ayrıca, tercüman (bash, perl, python, php, vb.) Kullanan bir komut dosyası ile nasıl yapabilirim?

Yanıtlar:


53

Setuid bit çalıştırdığınızda bunlar farklı ise, program dosyasının yerine gerçek kullanıcı sahibinin ayrıcalıklara sahip olması, böylece bir yürütülebilir dosya üzerinde ayarlanabilir. Bu, etkili kullanıcı kimliği (kullanıcı kimliği) ile gerçek kullanıcı kimliği arasındaki farktır .

Gibi bazı ortak yardımcı programlar, root'a passwdaittir ve zorunluluktan dolayı bu şekilde yapılandırılmıştır ( yalnızca root tarafından okunabilen passwderişime ihtiyacı vardır /etc/shadow).

Bunu yaparken en iyi strateji, hemen superuser olarak yapmanız gerekenleri yapmak ve daha sonra ayrıcalıkları düşürmektir, böylelikle kök çalıştırırken böcek veya kötüye kullanma olasılığı daha düşüktür. Bunu yapmak için, sürecin etkin kullanıcı arabirimini gerçek kullanıcı arabirimine ayarladınız . POSIX C’de:

#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 sistemlerinde yaygın olarak kullanılıyorsa, çoğu üst seviye dilde eşdeğeri olması gereken ilgili işlevler:

  • getuid(): Gerçek kullanıcı adını al.
  • geteuid(): Etkili kullanıcı adınızı alın .
  • seteuid(): Etkili kullanıcı adını ayarlayın .

Setuid biti çalıştırılabilir olarak ayarlandığı sürece , gerçek kullanıcı kimliği ile uygunsuz olan sonuncusu ile hiçbir şey yapamazsınız . Bunu denemek için derleyin gcc test.c -o testuid. Daha sonra ayrıcalıklarla yapmanız gerekir:

chown root testuid
chmod u+s testuid

Sonuncusu setuid bitini ayarlar. Şimdi ./testuidnormal bir kullanıcı olarak çalıştırıyorsanız , işlemin varsayılan olarak etkin kullanıcı kimliği 0, root ile çalıştığını görürsünüz.

Senaryolardan ne haber?

Bu, platformdan platforma değişir , ancak Linux'ta, bytecode da dahil olmak üzere bir tercüman gerektiren şeyler, tercüman üzerinde ayarlanmadıkça setuid biti kullanamaz (çok aptalca olur). İşte yukarıdaki C kodunu taklit eden basit bir perl betiği:

#!/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"; 

Buna göre * nixy kökleri, perl efektif uid ( $>) ve real uid ( $<) için özel değişkenlerde bulunur . Fakat aynı şeyi denerseniz chownve chmodderlenmiş (C'den, önceki örnekten) çalıştırılabilir ile birlikte kullanırsanız, hiçbir fark yaratmaz. Komut dosyası ayrıcalık alamıyor.

Bunun cevabı betiği çalıştırmak için setuid ikili kullanmaktır:

#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);
}

Derle gcc --std=c99 whatever.c -o perlsuido zaman chown root perlsuid && chmod u+s perlsuid. Artık, herhangi bir perl betiğini , kimin olduğuna bakılmaksızın, 0 etkili bir kullanıcı kimliği ile çalıştırabilirsiniz .

Benzer bir strateji php, python, vs. ile çalışacaktır. Ama ...

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

LÜTFEN LÜTFEN Etrafta böyle şeyler bırakmayın . Büyük olasılıkla, aslında betiğin adını mutlak bir yol olarak derlemek istiyorsunuz , yani içindeki tüm kodu main():

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

Onlar /opt/suid_scriptsve her şey root olmayan kullanıcılar için salt okunur olduğundan emin olun . Aksi takdirde, birisi herhangi bir şey için takas edebilir whatever.pl.

Ayrıca, birçok komut dosyası dilinin ortam değişkenlerinin bir komut dosyasını yürütme şeklini değiştirmelerine izin verdiğine dikkat edin . Örneğin, bir ortam değişkeni, arayan tarafından tedarik edilen bir kütüphanenin yüklenmesine neden olabilir ve böylece arayan kişinin kök olarak rasgele kod çalıştırmasına izin verebilir. Bu nedenle, hem tercümanın hem de komut dosyasının kendisinin tüm olası ortam değişkenlerine karşı dayanıklı olduğunu bilmiyorsanız, BU YAPMAYIN .

Öyleyse ne yapmalıyım?

Kök olmayan bir kullanıcının bir betiği kök olarak çalıştırmasına izin vermenin daha güvenli bir yolu bir sudo kuralı eklemek ve kullanıcının çalışmasını sağlamaktır sudo /path/to/script. Sudo, ortam değişkenlerinin çoğunu çıkarır ve ayrıca yöneticinin, komutu kimin çalıştıracağını ve hangi argümanlarla çalışacağını seçmesini sağlar. Parola sormadan belirli bir programı root olarak çalıştırma bölümüne bakın. Örneğin.


1
Bir çok kabuk, -privilegedkabuk olarak adlandırılırsa farklı davranacak ve sorumlu bir komut dosyasından çağrıldığında güvenli bir şekilde suid rootbu şekilde çağrılabilir . Ne yazık ki, sorumlu bir senaryo nosyonunun gerçek dünyada bir parça akış olduğunu düşünüyorum. Her neyse, eğer izinler yükseltilirken, eğer mümkünse her türlü
yazıdan

@mikeserv " -privilegedKabuk" ve "sorumlu senaryo" kavramlarına aşina değilim . Mermilerle ilgili başka bir cevap yapmak ister misiniz? Elbette kene söz veremem;) Bunu yapmak için pek iyi neden yok - sudoeğer mümkünse çok daha iyi bir seçenek - ben php sistem şifresi kimlik doğrulaması ile ilgili erken bir sorudan kaynaklanan genel bir cevap olarak yazdım .
goldilocks

1
- Gerçekten bunu yapmak istemiyorum sorumlu komut vardır gerçekten zor - beni aşar, muhtemelen. Ama senin analizi hemfikir söylemeliyim sudoben görüyor - sudoolarak psikotik o süsü içinde değil olması root. İçine kabuk küre bile koyabilirsin sudoers. subence kodlama amaçları sudoiçin daha iyi olsa da , canlı uygulamalar için iyidir. Fakat ne bir ile bir komut dosyası olarak açık gibidir #!/bin/ksh -pbangline ya da her türlü suid kshyer $PATHolduğunu.
mikeserv

Bu cevap soruyu ele alsa da, setuid komut dosyaları, kendinizi yerel bir ayrıcalık yükseltme güvenlik açığına açmanın bir reçetesidir. Senaryoların kolay anlaşılır hale getirilmemesinin bir nedeni var. Buradaki doğru cevap sudo.
mdadm

Cevabınızı, en azından çevre değişkenleriyle ilgili büyük güvenlik açığından bahsetme özgürlüğüne kavuştum. Kanonik bir cevap olarak bu kadar hoşlanmıyorum, çünkü güvensiz bir yöntemle (betikler için setuid sarmalayıcı) çok fazla sindirime giriyor. Sudo'yu önermek ve genişletilmiş tartışmayı başka bir konu için bırakmak en iyisidir (bu arada orada anlattım ).
Gilles 'SO- kötülük' dur

11

Evet yapabilirsin, ama muhtemelen çok kötü bir fikir . Genellikle, SUID bitini doğrudan çalıştırılabilir öğenize ayarlamazsınız, ancak çalıştırmak için bir sudo (8) veya su (1) kullanın (ve kimlerin yürütebileceğini sınırlayın)

Bununla birlikte, düzenli kullanıcıların programları (ve özellikle komut dosyalarını!) Root olarak çalıştırmalarına izin vermede birçok güvenlik sorunu vardır. Programın bunu ele almak için özellikle ve çok dikkatli bir şekilde yazılmış olmadıkça, çoğu kişi bunu yapmak zorunda kaldığında, kötü niyetli kullanıcılar onu kök kabuk elde etmek için kullanabilirler.

Bu nedenle, bunu yapsanız bile, ortamı, komut satırı parametreleri, STDIN ve işlediği tüm dosyalar, ağ bağlantılarından gelen veriler de dahil olmak üzere, TÜM girişi kök olarak çalıştırmak istediğiniz programa TÜM girdiyi sterilize etmek çok iyi bir fikir olacaktır. açılır, vb. vb. Yapması son derece zordur ve doğru yapılması daha zordur.

Örneğin, yalnızca bazı dosyaları düzenleyici ile düzenleyen kullanıcılara izin verebilirsiniz. Ancak editör dış yardımcıların komut çalıştırılmasına veya askıya alınmasına izin verir, böylece kullanıcılara istedikleri gibi yapmalarını sağlar. Veya sizin için çok güvenlikli görünen kabuk komut dosyalarını çalıştırıyor olabilirsiniz, ancak kullanıcı davranışını tamamen değiştiren değiştirilmiş $ IFS veya diğer ortam değişkenleriyle çalıştırabilir. Veya "ls" yi çalıştırması gereken PHP betiği olabilir, fakat kullanıcı onu $ PATH değiştirilmiş olarak çalıştırır ve böylece "ls" adını verdiği bir kabuk çalıştırmasını sağlar. Veya düzinelerce başka güvenlik sorunu var.

Program gerçekten çalışmasının bir kısmını root olarak yapmalıysa, normal kullanıcılar gibi çalışacak şekilde değiştirmesi en iyisi olacaktır, ancak kesinlikle (kesinlikle olabildiğince sterilize ettikten sonra) kesinlikle intihar yardımcısı programı aracılığıyla root ihtiyacı olan kısmı uygulayın.

Tüm yerel kullanıcılarınıza tamamen güveniyor olsanız bile (örneğin, onlara root şifresi verirseniz), HERHANGİ bir kimsenin (çevrimiçi bir PHP betiğinin olması veya zayıf bir şifreniz olması gibi) istenmeyen bir güvenlik denetimi olması kötü bir fikirdir. her neyse) aniden uzaktan saldırganın tüm makineyi tamamen tehlikeye atmasına izin verir.


1
seconded. bkz güvenli çağırma için POSIX programcının serisinde örnek man shbir başaramazsa bile ve - command -p env -i .... Sonuçta yapmak oldukça zor. Yine de, eğer doğru yapılırsa, açık amaçlar için, daha iyi olabilir suidyetenekli bir tercüman kullanımına daha suya sudo- ya birinin davranışı her zaman komut dosyasının kontrolü dışında olacak şekilde olsa ( suaz olasılıkla o eğilimi olarak eğri topları atılmasıdır biraz daha az delirmiş olmak) . Tüm paketi donatmak tek kesin bahis - hepsi olduğundan emin olmak daha iyiydi .
mikeserv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.