Czy skrypty mogą działać, nawet jeśli nie są ustawione jako pliki wykonywalne?

25

Mogę wydawać się uruchamiać skrypty (.sh) z ustawieniami plików wykonywalnych i bez nich. Więc gdzie to właściwie ma znaczenie?

Popiół
źródło

Odpowiedzi:

24

Załóżmy, że masz plik myscriptzawierający następujące elementy:

#!/bin/bash
echo "Hello, World!"

Jeśli uczynisz ten plik wykonywalnym i uruchomisz go ./myscript, jądro zobaczy, że pierwsze dwa bajty to #!, co oznacza, że ​​jest to plik skryptowy. Jądro wykorzysta resztę wiersza jako interpreter i przekaże plik jako pierwszy argument. Działa więc:

/bin/bash myscript

a bash czyta plik i wykonuje zawarte w nim polecenia.

Tak więc, aby bash (lub jakikolwiek interpreter wymagany przez twój skrypt) „wykonał” skrypt, musi tylko móc odczytać plik.

W przypadku skryptów bit wykonania po prostu sprawia, że ​​jego wykonanie jest nieco wygodniejsze. Tak długo, jak bash jest wykonywalny, zawsze możesz uruchomić bash z plikiem skryptu jako argumentem lub uruchomić bash interaktywnie i skopiować wklej skrypt wiersz po wierszu do terminala, aby wykonać polecenia.

geirha
źródło
Dziękujemy za szczegółowe wyjaśnienie. :) Jeśli dobrze to zrozumiałem, dostęp użytkownika do bash wymaga tylko dostępu do skryptu, aby go uruchomić, ponieważ bash weźmie skrypt jako dane wejściowe i będzie musiał go tylko przeczytać. Mogę zatrzymać to zachowanie, biorąc pozwolenie na odczyt skryptu dla tego użytkownika. Dobrze? Kiedy więc używane jest to uprawnienie do wykonywania i dokładnie to ma znaczenie?
Ashfame
Tak, jeśli użyjesz „bash myscript”, to użytkownik potrzebuje tylko dostępu do odczytu dla „myscript” (i oczywiście wykonywalny dla / bin / bash, jeśli bash znajduje się w ścieżce). Jeśli jednak sprawisz, że skrypt będzie wykonywalny, sytuacja będzie nieco inna. To prawda, że ​​z punktu widzenia jądra będzie to ponownie „/ bin / bash myscript”, jeśli pierwszy wiersz to #! / Bin / bash, ale aby osiągnąć ten punkt, najpierw musisz przedstawić skrypt jako wykonywalny dla użytkownik lub grupa. Jest to jednak prawdą, jeśli dla niektórych użytkowników skrypt nie jest wykonywalny, ale można go odczytać, ale nadal może „uruchomić” skrypt za pomocą „bash myscript” ....
LGB
@LGB Więc to prawie bezużyteczne. Dobrą rzeczą jest odcięcie uprawnienia do odczytu dla użytkownika dla tego skryptu. Dobrze?
Ashfame,
@Ashfame: Powiedziałbym raczej użyteczne niż bezużyteczne. Bit wykonania w zwykłych plikach nie jest (i nigdy nie miał być) używany do ograniczania dostępu. Wygląda na to, że oczekujesz tego po tym. Jeśli masz binarny plik wykonywalny, musisz mieć uprawnienia do wykonania, aby go uruchomić. Jeśli jednak masz do niego dostęp do odczytu, zawsze możesz skopiować plik do własnego katalogu domowego, w którym to przypadku kopia będzie twoją własnością, więc możesz dodać do niego uprawnienia do wykonywania ... i uruchomić go. W przypadku katalogów ma to jednak nieco inny cel. Zobacz mywiki.wooledge.org/Permissions
geirha
1
Czego powinienem użyć zamiast / bin / bash, jeśli nie znam poprawnego interpretera? Czy istnieje polecenie uruchamiające skrypt zgodnie z linią shebang?
Aivar,
16

Upewnij się, że nie mylisz „wykonywania skryptu powłoki” z „uruchom skrypt powłoki za pomocą sh”.

Uprawnienia do plików nie będą miały wpływu na file.sh:

sh file.sh

Wykonujesz sh(co powoduje przejście do programu /bin/sh), który czyta file.shi wykonuje jego kod.

Uprawnienia do plików będą obowiązywać, jeśli naprawdę wykonasz sam skrypt :

./file.sh

Pamiętaj, że uprawnienia do plików nie są obsługiwane przez systemy plików inne niż Linux, takie jak FAT. Więc nawet jeśli uruchomisz chmod -x file.sh, plik nadal będzie miał swoje wcześniejsze uprawnienia.

Uprawnienia do wykonywania są wymuszane przez system plików. Ale programy mogą również „wykonać” kod, odczytując zawartość pliku, co pomija uprawnienia systemu plików podczas „wykonywania”.

Lekensteyn
źródło
Rozumiem twój punkt widzenia. Ale czy to jest dla grupy, świata czy obu?
Ashfame,
@Ashfame Jeśli ustawisz uprawnienia do wykonywania, skrypt może być uruchamiany bezpośrednio przez użytkowników, którzy mają to uprawnienie - bez względu na to, czy posiadają je dla grupy, świata czy właściciela. Ale nawet ludzie bez pozwolenia na wykonanie mogą go wykonać, wywołując inny program (np. bash) W celu wykonania - aby zablokować, że będziesz musiał również odebrać im readpozwolenie.
jg-faustus
If you set the executable permission, the script can be run directly by users who have that permission - whether they have it on a group, world or owner basisAle w jaki sposób uprawnienia są przyznawane różnym użytkownikom poprzez sprawdzenie uprawnień do plików wykonywalnych? I dostałem twój drugi punkt. Masz na myśli odebranie im pozwolenia na odczyt skryptu, aby nie mogli go nawet przetworzyć przez bash. Dobrze?
Ashfame,
@Ashfame W punkcie zezwolenia na odczyt tak. Jak można wywołać coś sudo chmod g+x myfile.shw terminalu, aby dodać uprawnienia do wykonywania dla grupy plików. Zobacz samouczek uprawnień do plików . Aby zarządzać uprawnieniami dla kilku użytkowników jednocześnie, należy użyć grup, patrz na przykład Zarządzanie grupami .
jg-faustus
miałem na myśli to, że kiedy dodajemy uprawnienie do wykonania w GUI, to dla kogo? właściciel / grupa / świat?
Ashfame,
1

Nie myśl o tym w ten sposób. Czy mogę wykonać ten plik? Pomyśl o tym w następujący sposób: Kto może wykonać ten plik?

Jeśli komputer należy do Ciebie, a plik należy do Ciebie, jestem pewien, że możesz go wykonać. Możesz przyjrzeć się bliżej takim poleceniom jak chmod i chown oraz uprawnienia do plików.

Mam nadzieję że to pomogło.

myusuf3
źródło
Tak, wiem o nich. Oznacza to, że ja (właściciel) zawsze mogę to wykonać. Dobrze? Czy ustawienie pliku jako wykonywalnego dotyczy grupy, świata czy obu?
Ashfame,
1

execSyscall jądra Linux nie ze EACCESjeśli plik nie jest wykonywalny

Chociaż możesz to zrobić sh myprog.sh(co tylko czyta pliki i interpretuje), próba uruchomienia programu ./myprog.shjest niemożliwa, ponieważ kiedy to zrobisz:

Można to zweryfikować za pomocą main.c:

#define _XOPEN_SOURCE 700
#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    char *argv[] = {"myprog", NULL};
    char *envp[] = {NULL};
    int ret;
    ret = execve("myprog.sh", argv, envp);
    perror("execve");
    printf("%d\n", errno);
    printf("%d\n", EACCES);
}

i myprog.sh:

#!/bin/sh
echo worked

Jeśli myprog.shnie jest wykonywalny, mainkończy się niepowodzeniem z:

execve: Permission denied
13
13

Testowane w Ubuntu 17.10, gcc -std=c99.

POSIX 7 wspomina, że ​​w:

Funkcje exec, z wyjątkiem fexecve (), zawiodą, jeśli:

[EACCES] Odmówiono pozwolenia na wyszukiwanie dla katalogu wymienionego w prefiksie ścieżki nowego pliku obrazu procesu lub nowy plik obrazu procesu odmawia pozwolenia na wykonanie.

Dalsze uzasadnienie można znaleźć na stronie : /security/66550/unix-execute-permission-can-be-easily-bypassed-is-it-superfluous-or-whats-the

Ciro Santilli
źródło