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 passwd
aittir ve zorunluluktan dolayı bu şekilde yapılandırılmıştır ( yalnızca root tarafından okunabilen passwd
eriş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 ./testuid
normal 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 chown
ve chmod
derlenmiş (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 perlsuid
o 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_scripts
ve 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.
-privileged
kabuk olarak adlandırılırsa farklı davranacak ve sorumlu bir komut dosyasından çağrıldığında güvenli bir şekildesuid root
bu ş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ü