Pracuję nad aplikacją internetową, w której użytkownicy będą mogli dostarczać ciągi, które serwer następnie zastąpi zmiennymi.Czy ciąg napisów w formacie Python .format() może być bezpieczny dla niezaufanych ciągów formatów?
Najlepiej chciałbym użyć składni formatu PEP 3101() i zajmuję się możliwością nadpisania metod w Formatter, aby zapewnić bezpieczeństwo dla niezaufanych danych wejściowych.
Oto zagrożenia widzę z .format(), a to oznacza:
- wyściółka pozwala na określenie dowolnych długościach, tak '{:> 9999999999}'. Format (..) mógłby uruchomić serwer z pamięci i być DOS. Musiałbym to wyłączyć.
- Format pozwala uzyskać dostęp do pól wewnątrz obiektów, co jest przydatne, ale jest creepy, że można uzyskać dostęp do zmiennych dunder i rozpocząć wiercenia w bity standardowej biblioteki. Nie wiadomo, gdzie może być getattr(), który ma efekty uboczne lub zwraca coś tajnego. Dodałbym do białej listy dostęp do atrybutów/indeksu przez przesłonięcie funkcji get_field().
- Oczywiście musiałabym złapać kilka wyjątków.
Moje założenia są następujące:
- Żaden z tradycyjnym formacie C wyczynach smyczkowych dotyczą Pythona, ponieważ określając parametr to granice sprawdzony dostęp do kolekcji, zamiast bezpośrednio pstrykaliśmy stos wątku .
- Używana przeze mnie struktura sieci ucieka przed każdą zmienną, która jest podstawiana w szablonie strony, i dopóki jest to ostatni przystanek przed wyjściem, jestem bezpieczny przed atakami typu cross-site scripting wyłaniającymi się z de-escaping.
Jakie są Twoje myśli? Możliwy? Niemożliwy? Tylko nierozsądne?
Edit: Armin Ronacher nakreśla paskudny wyciek informacji, jeśli nie odfiltrować Dunder dostęp do zmiennych, ale wydaje się uważać zabezpieczania format(), jak to wykonalne:
{local_foo.__init__.__globals__[secret_global]}
http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/
(Osobiście nie przeszedłem do niezaufanego formatu format() w moim produkcie, ale aktualizuję je ze względu na kompletność)
Brzmi nierozsądnie. Nie możesz po prostu użyć 'replace()'? – grc
No cóż, dla funkcji start replace() wymaga podania hasła dla każdej zmiennej, która może znajdować się w łańcuchu, który skaluje się w sposób straszny. –
Lemmie rozwija tę wizję, ponieważ przegapiłem moją szansę na jej edycję. Mój przypadek użycia to sytuacja podobna do MUD, w której zamierzam zrobić tonę formatowania ciągów z dużą ilością potencjalnych zmiennych. Mogłabym wrócić do słabszej formy formatowania ciągów takich jak 'string.Template', ale możliwość odwoływania się do pól wewnątrz obiektów jest również bardzo przydatna w moim przypadku. To jest coś, co mogę naśladować, budując mapę parametrów każdego pola z każdego argumentu w każdym wywołaniu, ale byłoby to uspokajające, gdybym miał coś lepszego. –