GNU/Linux >> Znalost Linux >  >> Linux

Používáte Setuid Bit správně?

Mám proces, který při spuštění normálním uživatelem potřebuje oprávnění root. Zjevně k tomu mohu použít „setuid bit“. Jaký je správný způsob, jak to udělat v systému POSIX?

Také, jak to mohu udělat se skriptem, který používá interpret (bash, perl, python, php atd.)?

Přijatá odpověď:

Setuid bit lze nastavit na spustitelném souboru tak, že při spuštění bude mít program oprávnění vlastníka souboru namísto skutečného uživatele, pokud se liší. To je rozdíl mezi efektivní uid (ID uživatele) a skutečné uid.

Některé běžné nástroje, jako je passwd , jsou vlastněny root a konfigurovány tímto způsobem z nutnosti (passwd potřebuje přístup k /etc/shadow který může číst pouze root).

Nejlepší strategií, když to děláte, je udělat cokoli, co potřebujete udělat jako superuživatel hned, a poté snížit oprávnění, aby se při spuštění root s menší pravděpodobností vyskytly chyby nebo zneužití. Chcete-li to provést, nastavte proces jako efektivní uid ke svému skutečnému uid. V 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;
}

Relevantní funkce, které by měly mít ekvivalent ve většině jazyků vyšší úrovně, pokud se běžně používají v systémech POSIX:

  • getuid() :Získejte to skutečné uid.
  • geteuid() :Získejte efektivní uid.
  • seteuid() :Nastavte efektivní uid.

S posledním nevhodným pro skutečné uid nemůžete dělat nic kromě případů, kdy byl u spustitelného souboru nastaven bit setuid . Chcete-li to zkusit, zkompilujte gcc test.c -o testuid . Poté musíte s oprávněními:

chown root testuid
chmod u+s testuid

Poslední nastavuje bit setuid. Pokud nyní spustíte ./testuid jako normální uživatel uvidíte, že proces ve výchozím nastavení běží s efektivním uid 0, root.

A co skripty?

To se liší platformu od platformy, ale na Linuxu věci, které vyžadují interpret, včetně bytecode, nemohou využít setuid bit, pokud není nastaven na interpretu (což by bylo velmi hloupé). Zde je jednoduchý skript v perlu, který napodobuje výše uvedený kód 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"; 

V souladu se svými *nixy kořeny má perl vestavěné speciální proměnné pro efektivní uid ($> ) a skutečné uid ($< ). Ale pokud zkusíte stejný chown a chmod použitý s kompilovaným (z C, předchozí příklad) spustitelným souborem, nebude to mít žádný rozdíl. Skript nemůže získat oprávnění.

Související:Jak správně upgradovat bash na v4.0+?

Odpovědí na to je použití binárního souboru setuid ke spuštění skriptu:

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

Zkompilujte tento gcc --std=c99 whatever.c -o perlsuid , pak chown root perlsuid && chmod u+s perlsuid . Nyní můžete spustit jakékoli perl skript s efektivním uid 0, bez ohledu na to, kdo jej vlastní.

Podobná strategie bude fungovat s php, pythonem atd. Ale…

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

PROSÍM, NENECHÁVEJTE takové věci volně ležet . S největší pravděpodobností skutečně chcete kompilovat v názvu skriptu jako absolutní cestu , tj. nahradit veškerý kód v main() s:

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

Ujistěte se, že /opt/suid_scripts a vše v něm je pro uživatele bez oprávnění root pouze pro čtení. Jinak by někdo mohl vyměnit cokoli za whatever.pl .

Kromě toho mějte na paměti, že mnoho skriptovacích jazyků umožňuje proměnným prostředí změnit způsob provádění skriptu . Například proměnná prostředí může způsobit načtení knihovny dodané volajícím, což umožní volajícímu spustit libovolný kód jako root. Pokud tedy nevíte, že interpret i samotný skript jsou odolné vůči všem možným proměnným prostředí, NEDĚLEJTE TO .

Co mám tedy místo toho udělat?

Bezpečnějším způsobem, jak umožnit uživateli bez oprávnění root spustit skript jako root, je přidat pravidlo sudo a nechat uživatele spustit sudo /path/to/script . Sudo odstraňuje většinu proměnných prostředí a také umožňuje správci jemně vybrat, kdo může příkaz spustit a s jakými argumenty. Viz Jak spustit konkrétní program jako root bez výzvy k zadání hesla? pro příklad.


Linux
  1. Jak Sticky Bit funguje?

  2. Použití univerzálního šachového rozhraní

  3. Proč setuid bit funguje nekonzistentně?

  1. Odstraňte problémy s použitím souborového systému proc na Linuxu

  2. Použití síly na příkazovém řádku Linuxu

  3. Použití Redditu z konzole v roce 2020

  1. Co je to Rolling Release Linux a jaký je skutečný přínos jeho používání

  2. Použití –exclude With The Du Command?

  3. Účel použití Setuid() v programech Suid?