W języku programowania wykonuję proste polecenie powłoki
cd var; echo > create_a_file_here
z var jest zmienną, która zawiera ciąg (miejmy nadzieję) katalogu do miejsca, gdzie chcę, aby utworzyć plik „create_a_file_here”. Teraz, jeśli ktoś zobaczy ten wiersz kodu, można go wykorzystać, przypisując na przykład:
var = "; rm -rf /"
Sprawy mogą być dość brzydkie. Jednym ze sposobów uniknięcia powyższego przypadku może być przeszukanie ciągu w var dla znaków specjalnych, takich jak „;” przed wykonaniem polecenia powłoki, ale wątpię, czy obejmuje to wszystkie możliwe exploity.
Czy ktoś zna dobry sposób na to, aby „cd var” zmieniał tylko katalog i nic więcej?
shell-script
shell
ES___
źródło
źródło
var
jako argument. Na przykład dzwoniącsh
z argumentami-c
,'cd "$1"; echo > create_a_file_here'
,'sh'
,var
roboty i nie wymaga żadnych zmianvar
.'sh'
Argumentem jest przekazywana jako$0
.sh
, czy tworzysz własny język programowania z podobną składnią, ale który rozwija sięvar
zamiast wymagać pisaniacd "$var"
? Czy to jestbash
zshopt -s cdable_vars
? Och, myślę, że masz na myśli, że jakiś inny program prosi powłokę o uruchomienie tych poleceń. Więc po prostu zacytujvar
, ale upewnij się, że nie zawiera on samego znaku cudzysłowu ...s='"'; echo "$s"
odbitki"
.var=untrusted string
w programie nadrzędnym, podobnievar
jak zmienna środowiskowa, która jest już ustawiona podczas wywoływaniash
. Następnie musisz go zacytować za każdym razem, gdy go rozszerzysz, co można zrobić niezawodnie. Ach, widzę, że ten pomysł jest już częścią odpowiedzi Stéphane>. <Odpowiedzi:
Jeśli dobrze rozumiem,
var
to zmienna w twoim języku programowania.W swoim języku programowania prosisz powłokę o interpretację łańcucha, który jest konkatenacją
"cd "
, zawartością tej zmiennej i"; echo > create_a_file_here"
.Jeśli tak, jeśli zawartość
var
nie jest ściśle kontrolowana, jest to luka w zabezpieczeniach polegająca na wstrzykiwaniu poleceń.Możesz spróbować poprawnie cytować zawartość zmiennej¹ w składni powłoki, aby zagwarantować, że zostanie ona przekazana jako jeden argument do
cd
wbudowanego.Innym podejściem byłoby przekazanie zawartości tej zmiennej w inny sposób. Oczywistym sposobem byłoby przekazanie tego w zmiennej środowiskowej. Na przykład w C:
Tym razem kod, o który prosisz powłokę, aby ją zinterpretował, został naprawiony, nadal musimy go poprawnie zapisać w składni powłoki (tutaj zakłada się, że jest to powłoka zgodna z POSIX):
-P
docd
zrobić prostychdir()
--
zaznaczyć koniec opcji, aby uniknąć problemów zvar
rozpoczęciem-
(lub+
w niektórych powłokach)CDPATH
pusty ciąg na wypadek, gdyby znajdował się w środowiskuecho
Polecenie uruchamiamy tylko wtedy, gdy sięcd
powiedzie.Pozostaje (przynajmniej) jeden problem: jeśli
var
tak-
, to nie chdir do katalogu o nazwie,-
ale do poprzedniego katalogu (jak jest przechowywany w$OLDPWD
) iOLDPWD=- CDPATH= cd -P -- "$DIR"
nie ma gwarancji, że obejdzie go. Potrzebujesz więc czegoś takiego:¹ Pamiętaj, że samo wykonanie a nie
jest właściwą drogą, po prostu przenosisz problem.system(concat("cd \"", var, "\"; echo..."));
Na przykład
var = "$(rm -rf /)"
nadal byłby problem.Tylko niezawodny sposób, aby tekst wycenę dla Bourne-jak muszli jest użycie apostrofów , a także dbać o pojedynczych cytatów, które mogą wystąpić w ciągu. Na przykład zmień a
char *var = "ab'cd"
nachar *escaped_var = "'ab'\\''cd'"
. Oznacza to, że zastąpienie wszystkich'
do'\''
i owinąć całą sprawę wnętrze'...'
.Że nadal zakłada, że notowane ciąg nie jest używane w backticks, i że nadal potrzebne
--
,-P
,&&
,CDPATH=
...źródło
Proste rozwiązanie: nie wywołuj powłoki z programu. W ogóle.
Twój przykład tutaj jest trywialny, zmiana katalogu i tworzenie plików powinno być łatwe w dowolnym języku programowania. Ale nawet jeśli musisz uruchomić polecenie zewnętrzne, zwykle nie trzeba tego robić przez powłokę.
Tak więc np. W Pythonie, zamiast uruchamiać
os.system("somecmd " + somearg)
, użyjsubprocess.run(["somecmd", somearg])
. W C zamiastsystem()
, użyjfork()
iexec()
(lub znajdź bibliotekę, która to robi).Jeśli potrzebujesz użyć powłoki, zacytuj argumenty wiersza poleceń lub przekaż je przez środowisko, jak w odpowiedzi Stéphane'a . Ponadto, jeśli martwisz się postacią specjalną, poprawnym rozwiązaniem jest nie filtrowanie (czarnej listy) potencjalnie niebezpiecznych postaci, a jedynie utrzymywanie postaci bezpiecznych (biała lista).
Zezwól tylko na postacie, których funkcje znasz, w ten sposób zmniejsza się ryzyko pominięcia czegoś. Rezultatem końcowym może być to, że zdecydujesz się tylko na to
[a-zA-Z0-9_]
, ale to może wystarczyć, aby wykonać zadanie. Możesz także sprawdzić, czy twoje ustawienia regionalne i zestaw narzędzi nie zawierają liter akcentowanych takich jakä
i tamö
. Prawdopodobnie nie są uważane za specjalne przez żadną powłokę, ale znowu, lepiej być pewnym, czy zdadzą, czy nie.źródło
[a-zA-Z0-9]
, nie obejmuje rzeczy takich jakà
czyje kodowanie może być również źle interpretowane przez niektóre powłoki (jakbash
) w niektórych lokalizacjach.W języku programowania powinny istnieć lepsze sposoby wykonywania zadań niż wykonywanie poleceń powłoki. Na przykład zastąpienie
cd var
odpowiednikiem języka programowaniachdir (var);
powinno zapewnić, że wszelkie oszustwa o wartościvar
tylko powodują błąd „Nie znaleziono katalogu” zamiast niezamierzonych i prawdopodobnie złośliwych działań.Możesz także używać ścieżek bezwzględnych zamiast zmieniać katalogi. Wystarczy połączyć nazwę katalogu, ukośnik i nazwę pliku, którego chcesz użyć.
W C mogę zrobić coś takiego:
Z pewnością twój język programowania może zrobić coś podobnego?
źródło