Jak bezpiecznie przekazywać zmienne do skryptów z włączonym rootem?


13

To pytanie jest całkowicie ogólne i dotyczy nie tylko mojej sytuacji, ale ... Mam małe urządzenie busybox, w którym chcę, aby użytkownik inny niż root mógł wykonać określony skrypt z uprawnieniami administratora. Na przykład coś takiego jak ten mały skrypt do włączenia DHCP, gdzie jedyną zmienną ( $1) do wysłania na cmdline (!!) jest nazwa hosta do wysłania:

#!/bin/bash
udhcpc -b -i eth0 -h $1

uruchamianie udhcpc w ten sposób wymaga dostępu do konta root, więc w tym celu planuję zmodyfikować, /etc/sudoersaby zawierał ten wiersz:

joe ALL = NOPASSWD: /path/to/enable_dhcp.sh

które powinny umożliwić „Joe” łatwe uruchamianie tego skryptu z uprawnieniami administratora poprzez proste uruchomienie:

sudo /path/to/enable_dhcp.sh

i nie jest proszony o hasło (to jest to, czego chcę, ponieważ chcę, żeby Joe mógł to zrobić).

Teraz .. Wiem (a przynajmniej tak mi się wydaje), że użycie $1w skrypcie, który można łatwo uruchomić z uprawnieniami administratora, jest OGROMNYM pomysłem, ponieważ możesz do niego wstrzyknąć, co tylko chcesz.

Więc ... jaki jest najlepszy sposób, aby sobie z tym poradzić? Jak pozwolić Joe'emu robić, co chcę, z uprawnieniami roota, pozwalać mu przekazywać zmienną (lub skutecznie robić to tak, jak ze zmienną środowiskową), nie będąc jednocześnie szeroko otwartym na ataki iniekcyjne?

Odpowiedzi:


14

Uruchamianie skryptów powłoki pod sudojest bezpieczne, pod warunkiem, że sudojest skonfigurowane do resetowania środowiska . I odwrotnie, jeśli sudonie zresetuje środowiska, uruchomienie skryptu powłoki nie jest bezpieczne, nawet jeśli skrypt nie używa jego parametrów (zobacz Zezwalaj na setuid w skryptach powłoki ). Upewnij się, że masz Defaults env_resetw /etc/sudoersalbo, że ta opcja jest domyślnym czasu kompilacji ( sudo sudo -V | grep envpowinny zawierać Reset the environment to a default set of variables).

Używanie parametrów skryptu nie stanowi szczególnego zagrożenia. $1to ciąg znaków, wszystko, czego potrzebujesz, aby upewnić się, że używasz go jako łańcucha. (Na przykład nie rób eval "$1".) Oczywiście szczególnie ważne jest tutaj, aby nie przyjmować założeń dotyczących zawartości zmiennej i umieszczać podwójne cudzysłowy wokół wszystkich podstawień zmiennych (tj. Pisać "$1", nie $1). Zauważ, że umieszczanie podwójnych cudzysłowów wokół podstawień zmiennych nie jest specyficzne dla skryptów uruchamianych z uprawnieniami, jest to coś, co musisz robić cały czas.

Możesz dodatkowo sprawdzić poprawność parametru, w zależności od tego, co udhcpcrobi z czymś, co nie wygląda jak nazwa hosta. Na przykład wykona to pierwsze sprawdzenie składniowe:

#!/bin/sh
case "$1" in
  *[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"

Inne rzeczy, które należy wziąć pod uwagę, które mogą mieć wpływ na zachowanie tego polecenia: bieżący katalog roboczy i to, na co wskazują stdin, stdout, stderr, programy obsługi sygnałów i ulimity. Na przykład, zezwalając na zrzuty rdzenia (po <kbd> Ctrl- \ </kbd>), możesz pozwolić użytkownikowi na zaśmiecanie / uruchamianie / blokowanie, który w moim systemie jest tmpfs o bardzo ograniczonym rozmiarze i może pozwolić na DoS.
Stéphane Chazelas

5

Powinieneś dopasować przekazane dane wejściowe do znanego dobrego wzorca.

Na przykład wygląda na to, że adres IP może być dla Ciebie prawidłowy. Możesz więc użyć czegoś takiego:

if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
  udhcpc -b -i eth0 -h "$1"
else
  echo "Don't mess with me pork chop."
fi

Pamiętaj, że wyrażenie regularne nie zostało przetestowane, jesteś odpowiedzialny za upewnienie się, że wyrażenie regularne nie zezwala na nic niebezpiecznego.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.