Znam niektóre osoby, które obecnie pracują nad projektem dla amerykańskiego wojska (niski poziom bezpieczeństwa, dane o typie zasobów ludzkich niezwiązane z walką).
Początkowy stan kodu projektu został przesłany do wojska do przeglądu, a oni uruchomili program za pomocą pewnego rodzaju narzędzia do analizy bezpieczeństwa. Zwrócił raport o znanych problemach dotyczących bezpieczeństwa w kodzie i wymagał zmian, które należało wprowadzić przed dostarczeniem produktu końcowego.
Jednym z elementów, które należało rozwiązać, było usunięcie części projektu napisanej w języku Ruby, ponieważ jest to język dynamiczny.
Jaki jest powód / powód, dla którego nie można używać dynamicznego języka w bezpiecznym otoczeniu? Czy to rząd powoli wdraża nowe technologie? Czy też języki dynamiczne stanowią dodatkowe zagrożenie dla bezpieczeństwa w porównaniu do języków statycznych (ala C ++ lub Java )?
Odpowiedzi:
Istnieje wiele „schludnych” rzeczy, które można zrobić w dynamicznych językach, które można schować w częściach kodu, które nie są od razu oczywiste dla innego programisty lub audytora co do funkcjonalności danego fragmentu kodu.
Rozważ tę sekwencję w irb (interaktywna powłoka rubinowa):
To, co się tam zdarzyło, próbowałem wywołać metodę
foo
w stałej String. To się nie udało. Następnie otworzyłem klasę String i zdefiniowałem metodęfoo
return"foobar!"
, a następnie ją wywołałem. To zadziałało.Jest to znane jako klasa otwarta i daje mi koszmary za każdym razem, gdy myślę o pisaniu kodu w języku Ruby, który ma jakiekolwiek zabezpieczenia lub integralność. Pewnie, że pozwala ci robić porządne rzeczy dość szybko ... ale mógłbym to zrobić, aby za każdym razem, gdy ktoś przechowywał ciąg, zapisywał go w pliku lub wysyłał przez sieć. A ta odrobina przedefiniowania ciągu może być ukryta w dowolnym miejscu kodu.
Wiele innych dynamicznych języków ma podobne rzeczy do zrobienia. Perl ma Tie :: Scalar, który może za kulisami zmienić sposób działania danego skalara (jest to nieco bardziej oczywiste i wymaga określonego polecenia, które można zobaczyć, ale skalar, który jest przekazywany z innego miejsca, może stanowić problem). Jeśli masz dostęp do Perl Cookbook, poszukaj przepisu 13.15 - Tworzenie magicznych zmiennych za pomocą remisu.
Z powodu tych rzeczy (i innych często będących częścią dynamicznych języków) wiele metod statycznej analizy bezpieczeństwa w kodzie nie działa. Perl and Undecidability pokazuje, że tak jest i wskazuje nawet na tak trywialne problemy z podświetlaniem składni (
whatever / 25 ; # / ; die "this dies!";
stanowi wyzwanie, ponieważwhatever
można je zdefiniować tak, aby pobierało argumenty lub nie w czasie wykonywania całkowicie pokonało wyróżniacz składni lub analizator statyczny).To może stać się jeszcze bardziej interesujące w Ruby dzięki możliwości dostępu do środowiska, w którym zdefiniowano zamknięcie (patrz YouTube: Utrzymanie Ruby Rozsądne z RubyConf 2011 przez Joshua Ballanco). Dowiedziałem się o tym filmie od komentarza Ars Technica autorstwa MouseTheLuckyDog .
Rozważ następujący kod:
Ten kod jest w pełni widoczny, ale
mal
metoda może być gdzie indziej ... a przy otwartych klasach, oczywiście, mogłaby zostać zdefiniowana gdzie indziej.Uruchamianie tego kodu:
W tym kodzie zamknięcie mogło uzyskać dostęp do wszystkich metod i innych powiązań zdefiniowanych w klasie w tym zakresie. Wybrał metodę losową i przedefiniował ją, aby zgłosić wyjątek. (zobacz klasę Binding w Ruby, aby dowiedzieć się, do czego ten obiekt ma dostęp)
Krótsza wersja, która pokazuje redefinicję zmiennej:
Które, po uruchomieniu, produkuje:
To więcej niż wspomniana powyżej klasa otwarta, która uniemożliwia analizę statyczną. Powyżej pokazano, że zamknięcie, które jest przekazywane gdzie indziej, niesie ze sobą pełne środowisko, w którym zostało zdefiniowane. Jest to znane jako środowisko pierwszej klasy (tak jak kiedy można przekazywać funkcje, są to funkcje pierwszej klasy, to środowisko i wszystkie dostępne w tym czasie powiązania). Można było ponownie zdefiniować dowolną zmienną zdefiniowaną w zakresie zamknięcia.
Dobry czy zły, narzekający na ruby lub nie (są zastosowania, w których można chcieć dostać się do środowiska metody (patrz Bezpieczne w Perlu)), pytanie „dlaczego miałby ograniczać ruby dla projektu rządowego „tak naprawdę odpowiedź znajduje się w powyższym filmie wideo.
Jeśli się uwzględni:
Biorąc pod uwagę konsekwencje tych czterech wyborów projektowych, nie można wiedzieć, co robi każdy fragment kodu.
Więcej na ten temat można przeczytać na blogu Abstract Heresies . Ten szczególny post dotyczy Schematu, w którym odbyła się taka debata. (powiązane z SO: Dlaczego Schemat nie obsługuje środowisk pierwszej klasy? )
Mam nadzieję, że ten rozdział pokazuje niebezpieczny aspekt środowisk pierwszej klasy i dlaczego zostanie poproszony o usunięcie Ruby z dostarczonego rozwiązania. Nie chodzi tylko o to, że Ruby jest językiem dynamicznym (jak wspomniano w innym projekcie, inne języki dynamiczne były dozwolone w innych projektach), ale że istnieją specyficzne problemy, które sprawiają, że niektóre języki dynamiczne są jeszcze trudniejsze do uzasadnienia.
źródło
"many approaches to static analysis of security in code doesn't work"
, więc został odrzucony, ponieważ nie można go przeanalizować (przynajmniej przez tę grupę). Nie wiem, czy właściwie to interpretuję, czy jest to uzasadniony powód do odrzucenia.Zakładając, że ocena była tylko dla bezpieczeństwa, a nie tylko skanem akceptacji (tzn. Nie akceptują Ruby, ponieważ nie chcą obsługiwać Ruby):
Narzędzia do analizy bezpieczeństwa zwykle źle się zachowują przy zachowaniach dynamicznych.
Na przykład:
Uruchom dowolny projekt .NET napisany przy użyciu nowoczesnych funkcji, takich jak ASP.NET MVC i Entity Framework, poprzez coś takiego jak Veracode i zobacz, jaką listę fałszywych wyników pozytywnych otrzymujesz w swoim raporcie.
Veracode wymienia nawet wiele podstawowych technik bibliotek podstawowych .NET 4 jako „nieobsługiwane frameworki” jako nieobsługiwane lub tylko w wersji beta, chociaż większość z nich ma już kilka lat.
Jeśli masz do czynienia z podmiotem silnie polegającym na takim narzędziu, są prawie zmuszeni do rozważenia tych niepewnych, jeśli nie mają specjalistycznej wiedzy technicznej i zasobów, aby ręcznie ocenić projekt i sprawdzić, czy jest on poprawnie napisany i bezpieczne.
W operacjach cywilnych, w których systemy komputerowe na ogół nie kontrolują niczego niebezpiecznego lub strasznie kosztownego, łagodzenie polega na omawianiu fałszywych wyników pozytywnych i ogólnie są one ogólnie akceptowane.
W operacjach bankowych nadal masz szansę na fałszywie pozytywne złagodzenie, ale poświęcisz dużo więcej czasu na omawianie drobiazgów każdego elementu. Szybko staje się to kosztowne i zaczynasz używać bardziej tradycyjnych metod.
W wojsku, lotnictwie, przemyśle ciężkim i tym podobnych, systemy mogą kontrolować rzeczy, które mają straszne tryby awarii w tych systemach, dzięki czemu mogą mieć bardzo surowe reguły dotyczące języków, kompilatorów itp.
Organizacje generalnie piszą także swoje zasady bezpieczeństwa w najgorszym znanym im przypadku, więc nawet jeśli piszesz coś trywialnego, jeśli piszesz to dla organizacji, która ma nietrywialne systemy, domyślnie zazwyczaj będzie to utrzymywać wyższy standard, chyba że ktoś zażąda określonego wyjątku.
źródło
Języki dynamiczne mogą być używane w zastosowaniach obronnych i wojskowych. Osobiście korzystałem i dostarczałem Perla i Pythona w aplikacjach DoD. Widziałem również PHP i JavaScript używane i wdrażane. Z moich doświadczeń wynika, że większość nieskompilowanego kodu, który widziałem, to skrypty powłoki i Perl, ponieważ wymagane środowiska są zatwierdzone i zainstalowane w różnych możliwych systemach docelowych.
Fakt, że te języki są dynamiczne, najprawdopodobniej nie stanowi problemu. Tłumacze tych języków muszą zostać zatwierdzeni do użytku w systemach docelowych. Jeśli interpreter nie zostanie zatwierdzony do użycia (lub być może jest, ale nie jest wdrożony w systemach docelowych), wówczas nie można użyć języka. Korzystanie z danego interpretera (lub dowolnej aplikacji) w bezpiecznym systemie wymaga dowolnej liczby przeszkód bezpieczeństwa: analiza źródła, możliwość kompilacji ze źródła dla środowisk docelowych, dodatkowa analiza plików binarnych, zapewnienie braku konfliktów z istniejącą infrastrukturą itp.
źródło
Spędziłem trochę czasu na rozmowie z DOD (Departament Obrony), aby uzyskać kod pisania pozycji dla MMU F-16 . Bez naruszenia nieujawnienia: MMU to jednostka komputerowa, która kontroluje prawie wszystkie funkcje F-16. Jest (oczywiście) niezwykle ważne, aby podczas lotu nie występowały żadne błędy, takie jak błędy w czasie wykonywania. Równie ważne jest, aby system wykonywał operacje obliczeniowe w czasie rzeczywistym.
Z tego i innych historycznych powodów cały kod dla tego systemu jest napisany lub skompilowany w ADA, statycznym zorientowanym obiektowo języku programowania .
Nie lubię cytować zbyt wiele, ale to naprawdę wyjaśnia, dlaczego właśnie takie statyczne języki (jak ADA) są używane w takich projektach:
źródło
Zarówno DoD, jak i NASA mają długą historię, awarie programowania kosztowały ich miliardy dolarów. Obie instytucje zaakceptowały procesy, które powinny chronić je przed powtarzaniem tych samych błędów.
To nieporozumienie - dynamiczne języki nie są nową technologią, są dość stare. Problem polega na tym, że jeśli kiedykolwiek miałeś problem spowodowany przez dynamiczny język (np. Przez słabe / dynamiczne pisanie) i ten problem kosztuje dużo pieniędzy, możesz zaakceptować politykę, która uniemożliwiłaby ci powtórzenie tego samego błędu - np. zakaz używania dynamicznych języków w wrażliwych systemach.
Dynamiczne języki często „połykają” błędy i kończą się nieoczekiwanym zachowaniem. Jest to bardzo niebezpieczne w wrażliwych systemach. Jeśli dzieje się coś złego, musisz to wiedzieć jak najszybciej.
Jeśli chodzi o bezpieczeństwo, konieczne byłoby sprawdzenie rzeczywistego przypadku użycia. Na przykład nie sądzę, że strona internetowa Ruby on Rails byłaby automatycznie mniej bezpieczna niż strona Java.
źródło
Chciałbym dodać do istniejących odpowiedzi, opisując SA-CORE-2014-005 Drupala , która jest wysoce krytyczną luką, która umożliwia wstrzykiwanie SQL i ostatecznie wykonanie dowolnego kodu. Jest to spowodowane przez dynamiczne pisanie w PHP i luźne reguły pisania w czasie wykonywania.
Cała łatka dla tego problemu to:
Ten kod jest częścią warstwy abstrakcji SQL zaprojektowanej w celu zapobiegania wstrzykiwaniu SQL. Wymaga zapytania SQL o nazwanych parametrach i tablicy asocjacyjnej, która podaje wartość dla każdego nazwanego parametru. Wartość może być tablicą, dla przypadków takich jak
WHERE x IN (val1, val2, val3)
, w których wszystkie trzy wartości można przekazać jako pojedynczą wartość tablicową dla jednego nazwanego parametru.Luka występuje, ponieważ kod zakłada, że
$i
w$i => $value
musi być indeksem całkowitym wartości. Idzie dalej i łączy ten „indeks” bezpośrednio w zapytaniu SQL jako część nazwy parametru, ponieważ liczby całkowite nie wymagają żadnego znaku ucieczki, prawda?Niestety dla Drupala PHP nie daje takiej gwarancji. Możliwe jest przekazanie do innej tablicy asocjacyjnej, której klucze są ciągami, a ta pętla z radością połączy klucz ciągowy z zapytaniem w niezmienionej postaci (pamiętaj, że kod uważa, że może być tylko liczbą całkowitą).
Chociaż istnieją sposoby na uzyskanie podobnego błędu w języku o typie statycznym, są one mało prawdopodobne. Dobry programista zastanowi się, jakie
$i
mogą być rzeczy, zanim połączy to z zapytaniem. Dzięki statycznie wpisanemu językowi bardzo łatwo jest wymusić$i
liczbę całkowitą, a w takim wrażliwym dla bezpieczeństwa kodzie, jak to na pewno, można to zrobić.Ponadto kod faktycznie sprawdza, czy wartość jest tablicą przed iteracją po elementach. I tutaj leży druga część błędu, który umożliwia tę podatność: zarówno tablica asocjacyjna, jak i „normalna” tablica zwracają wartość true
is_array
. Chociaż prawdą jest również, że w języku C #, zarówno słowniki, jak i tabliceIEnumerable
, trudno jest zbudować kod, który połączyłby klucze słownika z takimi indeksami tablic nawet umyślnie, a tym bardziej przypadkowo.źródło
To, czy baza kodów jest bezpieczna, zależy od tego, jak piszesz kod, jak go testujesz oraz jak weryfikujesz i monitorujesz proces programowania i wdrażania. Języki nie są ani bezpieczne, ani niepewne, tak właśnie kodujesz.
Większość incydentów bezpieczeństwa spowodowanych przez złośliwe dane (zastrzyki SQL, przepełnienie bufora), wirusy, rootkity i trojany. Żaden język cię przed tym nie ochroni.
Zakazanie klasom języków bycia „niepewnym” nie jest uzasadnionym powodem.
Podejrzewam, że ktoś z jakiegokolwiek powodu - poinformowany lub nie - postanowił zakazać tych języków. Po pewnym czasie stało się to prawdą organizacyjną . Być może w tym momencie było to prawdą w przypadku niektórych projektów, ale kultury kontroli nie są skłonne do zmiany decyzji (przyznać, że były one błędne) i raczej preferują proste zasady. Żyją zgodnie z zasadami i przepisami i nie ma znaczenia, czy mają sens, czy nie, liczy się postrzegane bezpieczeństwo .
Dzieje się tak przez cały czas w kulturach kontrolnych. Widzę to mniej więcej codziennie. To nie ma sensu, ale tak to działa. Jeśli chcesz przeczytać więcej na ten bardzo istotny temat, polecam książkę Schneidera „ The Reengineering Alternative ”. Oto schemat kultury autorstwa Michaela Sahoto / Agilitrix , oparty na książce Schneidera:
źródło
O ile wiem, oficjalna polityka Departamentu Obrony zasadniczo nie zabrania używania dynamicznych języków.
Standardy oprogramowania opracowanego lub zamówionego przez DoD są ogłaszane przez Agencję Systemów Informacji Obronnej (DISA). Ich bezpieczeństwo aplikacji - Bezpieczeństwo aplikacji i bezpieczeństwo rozwoju Podręcznik wdrażania technicznego (STIG) nie zabrania żadnego konkretnego języka. Nie wspomina o Ruby, ale wspomina o Perlu i Pythonie, które są podobnie dynamiczne. Wymienia je w kontekście różnych tematów (przestrzeganie ustalonych standardów kodowania, unikanie luk w zabezpieczeniach związanych z wprowadzaniem poleceń itp.).
Prawdopodobnie to, co widzisz, jest zbyt surowym narzędziem skanującym (istnieje kilka różnych wymienionych w STIG, każde może mieć własną interpretację reguł) i / lub zbyt surową interpretacją wyników.
źródło