Czy istnieje powłoka, która sprawdza, czy kod jest podpisany?

19

W tym tygodniu bawiłem się PowerShellem i odkryłem, że musisz podpisać swoje skrypty, aby można je było uruchomić. Czy w Linuksie istnieje podobna bezpieczna funkcjonalność związana z zapobieganiem uruchamianiu skryptów bash?

Jedyną funkcjonalność podobną do tej, o której jestem świadomy, jest funkcja SSH wymagająca określonego klucza.

leeand00
źródło
2
Brzmi trochę jak ad-hoc rozwiązanie do podpisywania paczek do mnie. Nie wiem, czy Windows ma pakiet kryptograficzny podpisujący się tak jak Linux.
Wildcard,
6
@ leeand00 Skrypt jest specjalnym przypadkiem pakietu oprogramowania i nie widzę sensu, aby wyróżniać ten przypadek.
Gilles „SO- przestań być zły”
2
Mechanizm, który najbardziej mi się podoba, to sposób, w jaki robi to ChromeOS - umieszczenie jedynego systemu plików nie oznaczonego noexecna partycji tylko do odczytu na urządzeniu blokowym podpisanym metodą DM .
Charles Duffy,
1
source.android.com/security/verifiedboot mówi o przyjęciu tej funkcji Androida (początkowo ChromeOS).
Charles Duffy,
1
Możesz rozważyć bash jako zestaw poleceń, które można wpisać ręcznie w interfejsie wiersza poleceń. Po co ograniczać skrypty, skoro i tak możesz wpisać treść w wierszu poleceń?
Ding-Yi Chen,

Odpowiedzi:

11

Jeśli blokujesz możliwość uruchamiania skryptów przez sudoużytkowników, możesz skorzystać z tej digestfunkcji.
Możesz określić skrót skryptu / pliku wykonywalnego, w sudoersktórym zostanie zweryfikowany sudoprzed wykonaniem. Chociaż nie jest to to samo, co podpisywanie, daje podstawową gwarancję, że skrypt przynajmniej nie został zmodyfikowany bez modyfikacji sudoers.

Jeśli nazwa polecenia jest poprzedzona parametrem Digest_Spec, polecenie będzie pasować tylko wtedy, gdy będzie można je zweryfikować przy użyciu określonego skrótu SHA-2. Może to być przydatne w sytuacjach, gdy użytkownik wywołujący sudo ma dostęp do zapisu do polecenia lub jego katalogu nadrzędnego. Obsługiwane są następujące formaty skrótów: sha224, sha256, sha384 i sha512. Ciąg może być określony w formacie szesnastkowym lub base64 (base64 jest bardziej zwarty). Istnieje kilka narzędzi zdolnych do generowania skrótów SHA-2 w formacie szesnastkowym, takich jak openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

http://www.sudo.ws/man/1.8.13/sudoers.man.html

Batfastad
źródło
To mnie powstrzyma, dopóki nie przeczytam o SE Linux i nie zrobię tego dobrze.
leeand00,
13

Tak i nie.

Dystrybucja oprogramowania dla systemu Linux działa nieco inaczej niż dystrybucja oprogramowania dla systemu Windows. W (niewbudowanym) świecie Linuksa podstawową metodą dystrybucji oprogramowania jest dystrybucja (Ubuntu, Debian, RHEL, Fedora, Arch itp.). Wszystkie główne dystrybucje podpisują swoje pakiety systematycznie od około dekady.

Gdy oprogramowanie jest dystrybuowane niezależnie, od dostawcy zależy decyzja, w jaki sposób dostarczy swoje oprogramowanie. Dobrzy dostawcy zapewniają źródła pakietów zgodne z głównymi dystrybucjami (nie ma jednolitego mechanizmu dystrybucji dla całego systemu Linux: dystrybucja oprogramowania jest jednym z głównych punktów różnicowania między dystrybucjami) i które są podpisane kluczem dostawcy. Dystrybucje Linuksa rzadko działają jako organ podpisujący dla dostawców zewnętrznych (Canonical robi to z partnerami Ubuntu, ale obejmuje to bardzo niewielu dostawców) i myślę, że wszystkie główne dystrybucje używają sieci zaufania PGP, a nie infrastruktury klucza publicznego TLS, więc od użytkownika zależy, czy chce zaufać kluczowi.

Nie ma specjalnego mechanizmu, który wyróżniałby pakiety oprogramowania składające się z jednego skryptu z pakietów oprogramowania składających się z natywnego pliku wykonywalnego, pliku danych lub wielu plików. Żadna weryfikacja podpisu nie jest wbudowana w żaden wspólny interpreter skryptów, ponieważ weryfikacja pakietu oprogramowania jest kwestią całkowicie ortogonalną po uruchomieniu skryptu.

Myślę, że Windows adnotuje pliki z ich pochodzeniem i wymaga potwierdzenia użytkownika, aby uruchomić plik, którego pochodzenie jest „pobierane”, a nie „lokalne”. Linux tak naprawdę nie ma podobnego mechanizmu. Najbliższe jest uprawnienie do wykonywania: pobrany plik nie ma uprawnienia do wykonywania, użytkownik musi je wyraźnie włączyć ( chmod +xw wierszu polecenia lub w równoważnej akcji w menedżerze plików).

Gilles „SO- przestań być zły”
źródło
2
FWIW, oprócz tego programu PowerShell można skonfigurować (zgodnie z ustawieniami zasad), aby wykonywał tylko podpisane skrypty, a te zasady można skonfigurować tak, aby wszystkie skrypty były podpisane lub tylko skrypty „zdalnego pochodzenia”, lub żadnych skryptów. Działa najlepiej w środowisku AD z zarządzaniem kluczami i centralnym zarządzaniem polityką. To może być pomijany :-)
Stephen Harris
@StephenHarris No tak, jeśli ustawisz na obejście ...
leeand00
@ leeand00 - Najwyraźniej kodowanie base64 działa również jako obejście, ale nie wiem, czy zostało to zamknięte w nowszych wersjach programu PowerShell.
Stephen Harris,
1
@ leeand00 - patrz darkoperator.com/blog/2013/3/5/... dla zabawy :-) Zasadniczo przekaż skrypt zakodowany w standardzie base64 jako parametr w wierszu poleceń :-) Łatwo się owinąć!
Stephen Harris,
2
SeLinux adnotuje pliki według ich pochodzenia. To jedna z jego głównych siedzib.
loa_in_
10

Linux nie zapewnia możliwości ograniczenia wykonywania skryptów bash opartych na podpisach cyfrowych.

Trwają prace nad uwierzytelnianiem binarnych plików wykonywalnych. Więcej informacji na stronie https://lwn.net/Articles/488906/

Quentin Fennessy
źródło
Głosuj za bezpośrednią odpowiedzią bez sugerowania obejścia problemu.
user394,
8

Jednym słowem „nie”.

Linux tak naprawdę nie rozróżnia plików wykonywalnych i skryptów; #!na początku jest jakiś sposób powiadomić jądro, co program do uruchomienia w celu oceny wkładu, ale nie jest to jedyny sposób skrypt może być wykonywany.

Na przykład, jeśli mam skrypt

$ cat x
#!/bin/sh 
echo hello

Następnie mogę uruchomić to za pomocą polecenia

$ ./x

Spowoduje to, że jądro spróbuje go uruchomić, wykryje, #!a następnie efektywnie uruchomi /bin/sh x.

Mógłbym jednak również uruchomić dowolny z tych wariantów:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

lub nawet

. ./x

Więc nawet jeśli jądro próbuje wymusić podpisywanie na execwarstwie, możemy to obejść, uruchamiając interpreter tylko ze skryptem jako parametrem.

Oznacza to, że kod podpisu musiałby znajdować się w samym tłumaczu. A co powstrzymałoby użytkownika przed skompilowaniem własnej kopii powłoki bez kodu wymuszającego podpisanie?

Standardowym rozwiązaniem tego problemu nie jest korzystanie z podpisywania, ale stosowanie obowiązkowej kontroli dostępu (MAC), takiej jak SELinux. W systemach MAC możesz dokładnie określić, co każdy użytkownik może uruchamiać, i zmieniać warstwy. Na przykład można powiedzieć, że „normalni użytkownicy mogą uruchamiać wszystko, ale serwer WWW i procesy CGI mogą uzyskiwać dostęp tylko do danych z /var/httpdkatalogu; wszystko inne jest odrzucane”.

Stephen Harris
źródło
1
This means that signing code would have to be in the interpreter itself. And what would stop a user from compiling their own copy of a shell without the signing enforcement code?Nie pozwalając wykonywaniem wszelkich niepodpisanych plików wykonywalnych zrobi to, jeżeli użytkownik nie posiada klucza podpisującego. Istnieją już różne projekty * nix.
alzee,
2

Dystrybucje Linuksa zwykle mają gnupg . Wydaje mi się, że wszystko czego potrzebujesz to proste opakowanie bash, które sprawdza odłączony podpis gpg w stosunku do skryptu argumentu i uruchamia skrypt tylko wtedy, gdy sprawdzenie się powiedzie:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
PSkocik
źródło
Jedyne, czego to nie przedstawia, to uruchomienie skryptu, który ktoś właśnie stworzył ... na własną rękę ...
leeand00
2

Kontratakujące pytanie, które natychmiast przychodzi mi do głowy, brzmi: „Dlaczego miałbyś kiedykolwiek chcieć uniemożliwić użytkownikom uruchamianie programów, które napisali? ” Istnieje kilka możliwości:

  1. Dosłownie niemożliwe jest wykrycie, kto jest autorem kodu. Właścicielem pliku skryptu jest ten, kto faktycznie zapisał zawartość tego pliku, niezależnie od tego, skąd pochodzi. Wymuszanie podpisu jest więc skomplikowanym zamiennikiem okna dialogowego z potwierdzeniem: „Czy na pewno chcesz to zrobić?” W Linuksie część tego problemu rozwiązuje się transparentnie za pomocą podpisanych pakietów i ogranicza go fakt, że użytkownicy domyślnie mają ograniczony dostęp. Oczekuje się również, że użytkownik będzie wiedział, że uruchamianie kodu innych osób może być niebezpieczne *.
  2. Podobnie podpisywanie skryptu jest znacznie bardziej złożoną operacją niż zapisywanie pliku. W najlepszym przypadku zachęca to użytkownika do uświadomienia sobie, że wykonuje akcję podobną do podpisywania dokumentu i przed kontynuacją powinien sprawdzić, co mówi. Najprawdopodobniej po prostu zapewnia bardzo minimalny poziom biegłości technicznej ze strony użytkownika, aby móc uruchomić skrypt. W najgorszym przypadku pokazuje chęć przeskoczenia przez długą serię obręczy, by uruchomić to, co chcieli. W Linuksie * zakłada się biegłość techniczną.
  3. Bardziej prawdopodobne jest, że ludzie wykryją oczywiście złośliwy kod podczas pisania / wklejania szeregu poleceń do wiersza poleceń. Fragmenty tekstu jawnego przeznaczone do kopiowania i wklejania są zwykle mniejsze niż seria poleceń niezbędnych do zrobienia czegoś właściwie niecnego. Użytkownik może również ostrożnie skopiować i wkleić każdą linię osobno, rozumiejąc, co się dzieje. Dzięki skryptowi możliwe jest, że użytkownik nigdy nie spojrzał na kod. Może to być przydatna aplikacja podpisanych skryptów, przy zbyt powszechnym koszcie samozadowolenia po 12 razach, gdy trzeba to zrobić.

* Prawdopodobnie staje się to coraz mniej prawdziwe, ponieważ coraz więcej osób zaczyna korzystać z Linuksa

l0b0
źródło
1

Powodem, dla którego systemy ewoluowały inaczej, jest to, że Linux ma atrybut pliku „exec”, a Windows używa rozszerzeń plików w celu określenia wykonywalności.

W systemie Windows łatwo jest oszukać użytkownika, aby pobrał plik z rozszerzeniem „.exe”, „.bat”, „.scr”, który domyślnie będzie ukryty . Dwukrotne kliknięcie tego pliku zapewni wykonanie dowolnego kodu. W związku z tym opracowano duży mechanizm śledzenia pochodzenia i podpisywania plików wykonywalnych / skryptów w celu ograniczenia tego ryzyka.

W systemie Linux możesz uzyskać plik dla użytkownika, ale nie możesz łatwo zmusić do ustawienia bitu „exec”. Dodatkowo możliwe jest, aby całe systemy plików były „noexec”.

W każdym przypadku możesz jawnie uruchomić skrypt, wywołując interpretera. Możesz nawet tworzyć skrypty powłoki w czasie wykonywania i przesyłać je do „sh” lub uruchomić „sh -c”.

pjc50
źródło
0

Niestandardowo wiele programów do archiwizacji nie zachowuje bitów wykonawczych na zawartych plikach. To uniemożliwia uruchomienie dowolnych plików wykonywalnych. Cóż prawie.

Chodzi o to, co zostało opisane w innej odpowiedzi, że brak bitu wykonania nie uniemożliwia przekazania takiego skryptu bezpośrednio do bash. Chociaż można argumentować, że większość takich skryptów to bashskrypty, shebang może określić dowolny program jako interpreter. Oznacza to, że użytkownik musi uruchomić odpowiedni interpreter, jeśli zdecyduje się zignorować wykonywalną semantykę.

Chociaż nie jest to wiele, to w zasadzie obejmuje zapobieganie uruchamianiu niezaufanych plików wykonywalnych na * nixach z samym jądrem i powłoką .

Jak wspomniałem w jednym z komentarzy, istnieje jeszcze jedna warstwa ochrony SeLinux- która śledzi pochodzenie plików na podstawie zestawu reguł. Konfiguracja SeLinuxnie pozwoliłaby na przykład rootowi na uruchomienie pliku wykonywalnego z zestawem bitów wykonywalnych pobranym z Internetu, nawet jeśli skopiujesz i przeniesiesz plik. Można dodać regułę, że takie pliki można uruchamiać tylko przez inny plik binarny, który sprawdzałby podpis, podobnie jak w pytaniu.

Ostatecznie jest to kwestia konfiguracji najczęściej instalowanych fabrycznie narzędzi, a odpowiedź brzmi: tak .

loa_in_
źródło
wiele programów do archiwizacji nie zachowuje bitów wykonywanych na plikach zawartych . cóż, to jest pewien utrudnienie, gdy faktycznie chcesz go użyć do archiwizacji. Na szczęście tar ma zachować bit wykonania.
pjc50,
Musisz użyć tar -p źródła
loa_in_
-p, --preserve-permissions, --same-permissionsoznacza wyodrębnianie informacji o uprawnieniach do plików (domyślnie dla administratora)
loa_in_ 9.08.16
Nie, NIE potrzebujesz -p. Widzę, co mówi strona podręcznika, ale nie dzieje się tak. touch permtest; chmod +x permtest; tar cf permtest.tar.gz permtest; rm permtest; tar xf permtest.tar.gz; ls -l permtest- jest wykonywalny tutaj i nie jestem rootem.
domen
Spróbuję wtedy poprawić swoją odpowiedź.
loa_in_