GNU/Linux >> Belajar Linux >  >> Linux

Menggunakan Bit Setuid dengan Benar?

Saya memiliki proses yang membutuhkan hak akses root ketika dijalankan oleh pengguna biasa. Rupanya saya dapat menggunakan "setuid bit" untuk mencapai ini. Apa cara yang tepat untuk melakukan ini pada sistem POSIX?

Juga, bagaimana saya bisa melakukan ini dengan skrip yang menggunakan juru bahasa (bash, perl, python, php, dll)?

Jawaban yang Diterima:

Bit setuid dapat diatur pada file yang dapat dieksekusi sehingga ketika dijalankan, program akan memiliki hak istimewa dari pemilik file dan bukan pengguna sebenarnya, jika berbeda. Inilah perbedaan antara efektif uid (id pengguna) dan nyata uid.

Beberapa utilitas umum, seperti passwd , dimiliki root dan dikonfigurasi dengan cara ini karena kebutuhan (passwd perlu mengakses /etc/shadow yang hanya dapat dibaca oleh root).

Strategi terbaik saat melakukan ini adalah melakukan apa pun yang perlu Anda lakukan sebagai pengguna super segera kemudian menurunkan hak istimewa sehingga bug atau penyalahgunaan kecil kemungkinannya terjadi saat menjalankan root. Untuk melakukan ini, Anda menetapkan proses efektif uid ke uid aslinya. Di 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: %dn",
        real,
        geteuid()
    );
}

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

Fungsi yang relevan, yang seharusnya memiliki padanan di sebagian besar bahasa tingkat yang lebih tinggi jika digunakan secara umum pada sistem POSIX:

  • getuid() :Dapatkan yang nyata uid.
  • geteuid() :Dapatkan yang efektif uid.
  • seteuid() :Setel efektif uid.

Anda tidak dapat melakukan apa pun dengan yang terakhir tidak sesuai dengan uid asli kecuali sejauh bit setuid disetel pada yang dapat dieksekusi . Jadi untuk mencoba ini, kompilasi gcc test.c -o testuid . Anda kemudian perlu, dengan hak istimewa:

chown root testuid
chmod u+s testuid

Yang terakhir mengatur bit setuid. Jika sekarang Anda menjalankan ./testuid sebagai pengguna biasa, Anda akan melihat proses secara default berjalan dengan uid 0, root yang efektif.

Bagaimana dengan skrip?

Ini bervariasi dari platform ke platform, tetapi di Linux, hal-hal yang memerlukan juru bahasa, termasuk bytecode, tidak dapat menggunakan bit setuid kecuali jika diatur pada juru bahasa (yang akan sangat sangat bodoh). Berikut skrip perl sederhana yang meniru kode C di atas:

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

Sesuai dengan *nixy root-nya, Perl telah membangun variabel khusus untuk uid yang efektif ($> ) dan uid nyata ($< ). Tetapi jika Anda mencoba chown yang sama dan chmod digunakan dengan yang dikompilasi (dari C, contoh sebelumnya) dapat dieksekusi, itu tidak akan membuat perbedaan. Script tidak bisa mendapatkan hak istimewa.

Terkait:Bagaimana cara meningkatkan bash ke v4.0+ dengan benar?

Jawabannya adalah dengan menggunakan biner setuid untuk mengeksekusi skrip:

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

Kompilasi gcc --std=c99 whatever.c -o perlsuid , lalu chown root perlsuid && chmod u+s perlsuid . Sekarang Anda dapat menjalankan apa saja skrip perl dengan uid efektif 0, terlepas dari siapa pemiliknya.

Strategi serupa akan bekerja dengan php, python, dll. Tapi…

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

TOLONG TOLONG JANGAN biarkan hal semacam ini tergeletak begitu saja . Kemungkinan besar, Anda sebenarnya ingin mengkompilasi atas nama skrip sebagai jalur absolut , yaitu, ganti semua kode di main() dengan:

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

Mereka memastikan /opt/suid_scripts dan semua yang ada di dalamnya hanya-baca untuk pengguna non-root. Jika tidak, seseorang dapat menukar apa saja dengan whatever.pl .

Selain itu, berhati-hatilah karena banyak bahasa skrip memungkinkan variabel lingkungan mengubah cara mereka mengeksekusi skrip . Misalnya, variabel lingkungan dapat menyebabkan pustaka yang disediakan oleh pemanggil dimuat, memungkinkan pemanggil untuk mengeksekusi kode arbitrer sebagai root. Jadi, kecuali Anda tahu bahwa baik penerjemah maupun skrip itu sendiri kuat terhadap semua kemungkinan variabel lingkungan, JANGAN LAKUKAN INI .

Jadi, apa yang harus saya lakukan?

Cara yang lebih aman untuk mengizinkan pengguna non-root menjalankan skrip sebagai root adalah dengan menambahkan aturan sudo dan meminta pengguna menjalankan sudo /path/to/script . Sudo menghapus sebagian besar variabel lingkungan, dan juga memungkinkan administrator untuk memilih dengan halus siapa yang dapat menjalankan perintah dan dengan argumen apa. Lihat Bagaimana menjalankan program tertentu sebagai root tanpa prompt kata sandi? sebagai contoh.


Linux
  1. Bagaimana Cara Kerja Sticky Bit?

  2. Tujuan Menggunakan Setuid() Dalam Program Suid?

  3. Manfaat Nyata Menggunakan Uuids?

  1. Menjalankan aplikasi Qt melalui web

  2. kdevtmpfsi menggunakan seluruh CPU

  3. Apa overhead menggunakan subkulit?

  1. Memecahkan masalah menggunakan sistem file proc di Linux

  2. Menggunakan kekuatan di baris perintah Linux

  3. Mengapa bit setuid bekerja tidak konsisten?