Dlaczego rząd USA zabrania dynamicznych języków dla bezpiecznych projektów?

120

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 )?

Patrick
źródło
56
Jedynym sposobem, aby się upewnić, jest to, czy znajomi pytają pracodawców o powód. Ale mogę zaryzykować zgadywanie: statyczne sprawdzanie typu to kolejna warstwa, która pomaga w poprawności oprogramowania o znaczeniu krytycznym. Oczywiście nie pozbędzie się błędów, ale jest to krok we właściwym kierunku: komputer wykonuje za ciebie część pracy. (Tak, wiem, że to terytorium świętych wojen).
Andres F.,
4
Możliwe, że istotne: williamedwardscoder.tumblr.com/post/42912076785/...
Robert Harvey
75
Nie chcesz, aby oprogramowanie do kontroli rakiet zostało napisane w PHP + JavaScript.
Tulains Córdova
16
Dane HR nie są „niskim poziomem bezpieczeństwa”. Oczekiwałbym, że firma zapewni moje bezpieczeństwo zatrudnienia i dane osobowe tak bezpiecznie, jak to tylko możliwe.
gbjbaanb
5
@gbjbaanb Myślę, że OP oznaczało, że utrata życia nie jest tutaj najgorszym scenariuszem.
Andres F.,

Odpowiedzi:

126

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):

irb(main):001:0> "bar".foo
NoMethodError: undefined method `foo' for "bar":String
        from (irb):1
        from /usr/bin/irb:12:in `<main>'
irb(main):002:0> class String
irb(main):003:1> def foo
irb(main):004:2> "foobar!"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> "bar".foo
=> "foobar!"

To, co się tam zdarzyło, próbowałem wywołać metodę foow stałej String. To się nie udało. Następnie otworzyłem klasę String i zdefiniowałem metodę fooreturn "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ż whatevermoż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:

def mal(&block)
    puts ">:)"
    block.call
    t = block.binding.eval('(self.methods - Object.methods).sample')
    block.binding.eval <<-END
        def #{t.to_s}
          raise 'MWHWAHAW!'
        end
    END
end

class Foo
    def bar
        puts "bar"
    end

    def qux
        mal do
            puts "qux"
        end
    end
end

f = Foo.new
f.bar
f.qux

f.bar
f.qux

Ten kod jest w pełni widoczny, ale malmetoda może być gdzie indziej ... a przy otwartych klasach, oczywiście, mogłaby zostać zdefiniowana gdzie indziej.

Uruchamianie tego kodu:

~ / $ ruby ​​foo.rb 
bar
> :)
qux
bar
b.rb: 20: in `qux ': MWHWAHAW! (RuntimeError)
    from b.rb: 30: in ''
~ / $ ruby ​​foo.rb 
bar
> :)
qux
b.rb: 20: in `bar ': MWHWAHAW! (RuntimeError)
    from b.rb: 29: in ''

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)

Wszystkie zmienne, metody, wartość self i ewentualnie blok iteratora, do których można uzyskać dostęp w tym kontekście, są zachowane.

Krótsza wersja, która pokazuje redefinicję zmiennej:

def mal(&block)
    block.call
    block.binding.eval('a = 43')
end

a = 42
puts a
mal do 
  puts 1
end
puts a

Które, po uruchomieniu, produkuje:

42
1
43

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:

  1. Ruby pozwala wyodrębnić środowisko z dowolnego zamknięcia
  2. Ruby przechwytuje wszystkie wiązania w zakresie zamknięcia
  3. Ruby zachowuje wszystkie wiązania jako aktywne i zmienne
  4. Ruby ma nowe wiązania cień starych powiązań (zamiast klonowania środowiska lub zabrania ponownego wiązania)

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? )

Z czasem jednak zdałem sobie sprawę, że w środowiskach pierwszej klasy było więcej trudności i mniej mocy, niż początkowo sądziłem. W tym momencie uważam, że pierwszorzędne środowiska są w najlepszym wypadku bezużyteczne, aw najgorszym niebezpieczne.

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.

Społeczność
źródło
3
Nie rozumiem sensu tego. Wspominasz o klasie Perla, która pozwala na zmianę zachowania skalarów. Jednak Perl jest szeroko stosowany, w tym w bezpiecznych środowiskach. Po prostu posiadanie tych możliwości w języku nie oznacza, że ​​języka nie można używać. W konkretnym przypadku Ruby prawdopodobnie środowisko docelowe nie obsługuje Ruby. Osobiście nigdy nie widziałem Ruby dostępnego do użytku na żadnym systemie i nawet nie jestem pewien, czy znajduje się na liście zatwierdzonych programów.
Thomas Owens
17
@ThomasOwens - Rozumiem tę odpowiedź, że klucz jest "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.
Bobson
21
Brakuje informacji na temat zatwierdzonych list oprogramowania, mogę jedynie zgadywać, jakie są trudności z dynamicznymi językami. Widziałem jednak podobne problemy z oprogramowaniem finansowym i nieudane kontrole branży kart płatniczych, ponieważ w języku nie można było przeprowadzić analizy statycznej pod kątem bezpieczeństwa. Zademonstrowałem dwa przykłady w dynamicznych językach, w których natura języka pozwala mu obalić analizę statyczną. Wskazałem również, dlaczego nawet teoretycznie nie może to być dokładne. Może być tak, że Perl jest dozwolony w niektórych miejscach, a nie w innych, mogę tylko zgadywać co do przyczyn.
2
Możesz również na nowo zdefiniować standardowe funkcje biblioteczne w wielu innych językach (na przykład Obj-C, C, C ++).
Martin Wickman
12
Cóż, metody rozszerzenia .NET NIE są takie same jak powyższy Ruby. Po prostu tworzą łatwiejszy sposób na wpisanie klasy statycznej. W rzeczywistości nie dodają metody do klasy.
Graham
50

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.

Rachunek
źródło
4
I to tylko fałszywe pozytywy. Naprawdę niepokojąca jest możliwość fałszywych negatywów.
Stephen C
3
Szczerze mówiąc, moje doświadczenie z tymi narzędziami było ogólnie okropne. Prawdopodobnie coś w tempie od 1/200 do 1/1000 znalezienia czegoś, co naprawdę warto omówić. Ponadto, kiedy otrzymuję fałszywy pozytyw, wiem, że coś jest używane w tysiącach miejsc w bazie kodu lub frameworku i zidentyfikowało to tylko kilka razy, nie jestem do końca pewny. Problem polega na tym, że skutecznie wdrażasz dowód negatywny, gdy budujesz jedno z tych narzędzi, chyba że zaczynasz od języka formalnego, takiego jak spec #.
Bill
33

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.

Thomas Owens
źródło
32

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 .

Ze względu na funkcje wsparcia krytyczne dla bezpieczeństwa Ady, jest on teraz wykorzystywany nie tylko do zastosowań wojskowych, ale także w projektach komercyjnych, w których błąd oprogramowania może mieć poważne konsekwencje, np. Awionika i kontrola ruchu lotniczego, rakiety komercyjne (np. Ariane 4 i 5), satelity i inne systemy kosmiczne, transport kolejowy i bankowość. Na przykład oprogramowanie systemowe fly-by-wire w Boeing 777 zostało napisane w Adzie.

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:

Obsługiwana jest duża liczba kontroli w czasie kompilacji, aby uniknąć błędów, które nie byłyby wykrywalne do czasu uruchomienia w niektórych innych językach lub wymagałyby jawnych kontroli w kodzie źródłowym. Na przykład składnia wymaga jawnie nazwanego zamykania bloków, aby zapobiec błędom wynikającym z niedopasowanych tokenów końcowych. Przestrzeganie silnego pisania pozwala wykryć wiele typowych błędów oprogramowania (błędne parametry, naruszenia zakresu, nieprawidłowe odwołania, niedopasowane typy itp.) Albo w czasie kompilacji, albo w inny sposób w czasie wykonywania. Ponieważ współbieżność jest częścią specyfikacji języka, kompilator może w niektórych przypadkach wykryć potencjalne zakleszczenia. Kompilatory często sprawdzają również błędnie napisane identyfikatory, widoczność pakietów, zbędne deklaracje itp. Oraz mogą udostępniać ostrzeżenia i przydatne sugestie dotyczące sposobu naprawienia błędu.

Ada obsługuje również kontrole w czasie wykonywania w celu ochrony przed dostępem do nieprzydzielonej pamięci, błędami przepełnienia bufora, naruszeniami zasięgu, błędami off-by-one, błędami dostępu do tablicy i innymi wykrywalnymi błędami. Te kontrole można wyłączyć w celu zwiększenia wydajności środowiska wykonawczego, ale często można je skutecznie skompilować. Obejmuje również udogodnienia ułatwiające weryfikację programu. Z tych powodów Ada jest szeroko stosowana w systemach krytycznych, gdzie jakakolwiek anomalia może prowadzić do bardzo poważnych konsekwencji, np. Przypadkowej śmierci, obrażeń lub poważnych strat finansowych. Przykłady systemów, w których stosuje się Adę, obejmują awionikę, koleje, bankowość, wojsko i technologię kosmiczną.

Dynamiczne zarządzanie pamięcią Ady jest bezpieczne i bezpieczne dla każdego typu. Ada nie ma ogólnych (i niejasnych) „wskaźników”; nie deklaruje też domyślnie żadnego typu wskaźnika. Zamiast tego wszystkie dynamiczne przydzielanie i zwalnianie pamięci musi odbywać się poprzez jawnie zadeklarowane typy dostępu. Każdy typ dostępu ma powiązaną pulę pamięci, która obsługuje szczegóły niskiego poziomu zarządzania pamięcią; programista może albo użyć domyślnej puli pamięci, albo zdefiniować nowe (dotyczy to szczególnie niejednorodnego dostępu do pamięci). Możliwe jest nawet zadeklarowanie kilku różnych typów dostępu, które wszystkie oznaczają ten sam typ, ale używają różnych pul pamięci. Ponadto język zapewnia sprawdzanie dostępności, zarówno w czasie kompilacji, jak i w czasie wykonywania, co zapewnia, że ​​wartość dostępu nie może przeżyć typu obiektu, na który wskazuje.

Michael Jasper
źródło
3
„Ze względu na funkcje wsparcia krytyczne dla bezpieczeństwa Ady jest ona obecnie [stosowana] w komercyjnych rakietach (np. Ariane 4 i 5)” , oczywiście pierwsza Ariane 5 wybuchła z powodu błędu oprogramowania , więc nie ma srebrnej kuli.
Andrew Marshall,
5
@AndrewMarshall: „Chociaż raport zidentyfikował błąd oprogramowania jako bezpośrednią przyczynę, inni badacze widzą przyczyny jako awarie projektu systemu i problemy z zarządzaniem” - Poważnie wątpię, aby kod napisany w innym języku (np. Java lub C ++) otrzymał rakieta na orbitę.
Martin Schröder
@ MartinSchröder Och, nie wątpię, że Ada jest prawdopodobnie lepsza od innych w tej aplikacji, tylko zauważając, że nie jest głupia. Inny język mógł przepuścić niezliczone błędy, które po prostu nie byłyby możliwe w Adzie.
Andrew Marshall
13

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.

Is this the government being slow to adopting new technologies?

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.

Sułtan
źródło
2
IMHO więcej błędów zostało „połkniętych” przez niewykryte przepełnienia bufora niż cokolwiek innego, co jest dokładnie czymś, na co większość dynamicznych języków nie pozwoli przede wszystkim ... po prostu
miraculixx
@miraculixx Prawda, istnieje powód, dla którego Java / C # i podobne języki są używane znacznie częściej niż Ruby. Są defensywni - sprawdzają wszystko. W C / C ++ defensywność można wzmocnić, stosując dobre standardy kodowania. Możesz również wymusić kontrole na wszystko. Ale czy możesz sobie wyobrazić pisanie wrażliwej aplikacji w języku ruby ​​lub javascript? Możliwość ukrywania błędów jest świetna.
Sulthan,
Rzeczywiście mogę. Prawdopodobnie zgadzamy się, że oprogramowanie musi zostać dokładnie przetestowane, niezależnie od języka programowania. Aby uniknąć regresji, testy najlepiej zautomatyzować przy użyciu np. Testów jednostkowych, BDD i in. Zakładając profesjonalne podejście (delikatna aplikacja, prawda?), Osiągnięcie wystarczającego zasięgu testu jest procesem zarządzanym, a nie pozostawionym przypadkowi. W związku z tym wątpię, aby C / C ++, Java miały przewagę nad takimi jak ruby ​​lub javascript pod względem ukrytych błędów. Umiejętności programistyczne? Prawdopodobnie bardziej techniczny w C ++, wątpliwy w Javie, ale prawie nie ma problemu z językiem. Bardziej techniczny! = Jakość produktu.
miraculixx
6

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:

-      foreach ($data as $i => $value) {
+      foreach (array_values($data) as $i => $value) {

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 jakWHERE 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 $iw$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 $imogą być rzeczy, zanim połączy to z zapytaniem. Dzięki statycznie wpisanemu językowi bardzo łatwo jest wymusić $iliczbę 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 tablice IEnumerable, trudno jest zbudować kod, który połączyłby klucze słownika z takimi indeksami tablic nawet umyślnie, a tym bardziej przypadkowo.

Roman Starkov
źródło
2

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: wprowadź opis zdjęcia tutaj

Martin Wickman
źródło
18
-1 Istnieje wiele ważnych technicznych powodów, dla których język zostałby wybrany zamiast innego (sprawdzanie w czasie rzeczywistym, pisanie statyczne, sprawdzanie w czasie wykonywania) dla systemów o krytycznym znaczeniu dla bezpieczeństwa. Sugerujesz, że przyczyny są w 100% kulturą, my kontra oni, i arbitralne, co IMO jest całkowicie niepoprawne w tym przypadku.
Michael Jasper
8
„Języki nie są ani bezpieczne, ani niebezpieczne” - patrz stackoverflow.com/a/14313277/602554 . Niektóre języki są zdecydowanie „bezpieczniejsze” niż inne.
Michael Jasper
2
Zaktualizowałem moją odpowiedź, być może do twoich upodobań. Nadal uważam, jak bezpieczny jest system, ponieważ zależy on bardziej od pisanego kodu niż używanego języka, chociaż niektóre języki pomagają uniknąć pewnych problemów (a jednocześnie mogą wprowadzać inne).
Martin Wickman
2
@MartinWickman: a) Zastrzyki SQL / HTML i przepełnienia buforów są rozwiązywane przez niektóre systemy typów - masz różne typy dla znaków ucieczki i nieskalowanych, więc wiesz, które powinny być traktowane w jaki sposób. b) nie wszystkie kwestie bezpieczeństwa w „bezpiecznych projektach” niekoniecznie oznaczają kompromis. Nie chcę, aby oprogramowanie działające w samolocie miało jakiś błąd, nawet jeśli nie jest to kwestia „bezpieczeństwa” (tzn. Nie można go użyć do przejęcia systemu).
Maciej Piechotka,
5
-1 dla problemów z dokładnością faktyczną. Exploity przepełnienia bufora są problemem ściśle specyficznym dla języka C. nigdy nie słyszysz o nich w językach, które nie pozwalają ci przydzielić bufora łańcuchów na stosie. I wcale nie jest trudno wyobrazić sobie hipotetyczny dialekt SQL, w którym użycie parametrów nie było po prostu dozwolone, ale wymagane . Wstrzyknięcie SQL byłoby niemożliwe w tym języku. Tak, odpowiednio zaprojektowany język może chronić cię przed kilkoma typowymi rodzajami ataków.
Mason Wheeler
2

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.

Andrew Medico
źródło