Udostępnij swój język do analizy / audytu dla osób zajmujących się bezpieczeństwem komputerowym.
Pracownicy ochrony muszą być w stanie znaleźć luki w zabezpieczeniach programu przed jego wysłaniem. Najlepiej, gdy jesteśmy wzywani wcześnie i możemy komentować bazę kodu w miarę jej rozwoju, ale często nie.
Gdy pojawi się nowa wersja języka lub bibliotek podstawowych, rzeczy, które wcześniej były bezpieczne, mogą już nie być:
- biblioteki mogą stać się potężniejsze: np. biblioteka URL obsługuje teraz
javascript:
- mogą istnieć nowe sposoby konwertowania ciągów lub bajtów na kod: np.
eval
biblioteki deserializacji
- techniki refleksji językowej mogą stać się silniejsze: np. ujawnianie zmiennych lokalnych
Każda z tych zmian może zwiększyć liczbę uprawnień nadużycia, jakie ma program, ale ponieważ ilość uprawnień, z których korzysta program (w kontaktach z nie-złośliwymi klientami), nie uległa zmianie, pracownicy ochrony są zmuszeni dowiedzieć się o tym bez intensywnego ponowny audyt.
Proszę więc pomyśleć o nas przy projektowaniu i wersjonowaniu języka. Poniżej znajduje się kilka wskazówek:
Zdefiniuj kilka prymitywów, na które program może zostać rozłożony.
HTML5 jest szczególnie zły w ten sposób. Oczywiście poświęcili wiele uwagi bezpieczeństwu i mają bardzo inteligentnych ludzi, ale zamiast określać nowe elementy programu, takie jak <video>
stare, lub tworzyć wspólną abstrakcję, którą można określić zarówno nowe, jak <video>
i stare <img>
, <video>
to jeszcze kolejny jednorazowy element programu z własnymi konsekwencjami bezpieczeństwa.
Uczyń swój język podatnym na analizę statyczną (nawet jeśli nie jest statycznie wpisany).
Specjaliści od bezpieczeństwa często używają analizy statycznej, aby znaleźć wzorce i spróbować wykluczyć części programu, aby mogli skupić się na naprawdę trudnych bitach.
Powinno być oczywiste, które identyfikatory są zmiennymi lokalnymi, a które nie.
Np. Nie popełniaj tego samego błędu co w starych wersjach JavaScript, które uniemożliwiały stwierdzenie, czy x
poniżej znajduje się odwołanie do zmiennej lokalnej (zgodnie z dosłownym odczytem starej wersji specyfikacji):
if (Math.random() > 0.5) {
Object.prototype.x = 0;
}
function f() {
var x = 1;
(function () {
alert(x); // Might alert 0, might alert 1.
})();
}
Pozwól na bezpieczeństwo rozkładalne
Wiele bezpiecznych systemów zostało zaprojektowanych wokół bezpiecznego jądra, które zachowuje właściwości bezpieczeństwa, dzięki czemu osoby zajmujące się bezpieczeństwem mogą skoncentrować swoje wysiłki na analizie niewielkiej ilości kodu i uwolnić większość programistów od konieczności radzenia sobie z osobami zajmującymi się bezpieczeństwem {irytujące, pedantyczne, paranoiczne} .
Powinno być możliwe napisanie takiego jądra w twoim języku. Jeśli jedną z właściwości bezpieczeństwa twojego języka jest to, że kiedykolwiek zostanie pobrany tylko pewien podzbiór adresów URL, czy pisarze jądra mogą zrobić coś, by skierować wszystkie pobieranie adresów URL przez swój kod? Lub może statyczne kontrole kompilacji (np. Patrząc na import) pełnią tę samą funkcję.
Niektóre języki, takie jak Newspeak, używają modelu możliwości obiektu. To niesamowity i świetny sposób na uzyskanie bezpieczeństwa rozkładalnego.
Ale jeśli nie możesz tego zrobić, uczynienie z wykresu modułu artefaktu, który można analizować statystycznie, może przynieść ci wiele korzyści. Jeśli mogę udowodnić, że moduł nie może dotrzeć do modułu we / wy pliku (z wyjątkiem wywoływania kodu w module w TCB), to mogę wykluczyć całe klasy problemów z tego modułu.
Ogranicz uprawnienia wbudowanych języków skryptowych
Wiele przydatnych systemów jest zorganizowanych jako statyczny rdzeń, który odpycha dużo kodu napisanego w dynamicznych (nawet funkcjonalnych) językach.
Osadzanie języków skryptowych może znacznie rozszerzyć system.
Ale język skryptowy nie powinien mieć pełnych uprawnień maszyny wirtualnej.
Jeśli zdecydujesz się zezwolić na wbudowane języki skryptowe, ułatw inwokatorowi ograniczenie tego, co mogą zrobić. Model właściwości obiektowych (patrz komentarz do Newspeak powyżej) jest tutaj bardzo odpowiedni; dlatego podczas oceny kodu w języku skryptowym wywołujący powinien przekazać kod do wykonania i wszystkie zmienne globalne dla tego kodu.
Traktuj eval
jako język osadzający się jako język skryptowy
Jeśli Twój język może wywoływać własny kompilator w celu przekształcenia łańcucha w kod, pozwól, aby został on piaskowiony tak samo, jak każdy osadzony język skryptowy.
Użyj prostego modelu współbieżności
My, ochroniarze, nie chcemy martwić się warunkami wyścigowymi, próbując dowiedzieć się, czy własność bezpieczeństwa jest utrzymywana.
Zanim zdecydujesz się na wątki, rozważ alternatywę dla wątków jako prawie niemożliwą do zabezpieczenia domyślną opcję.
Jednym prostym jest współbieżność pętli zdarzeń, taka jak w E, Verilog i JavaScript.
Nie zachęcaj do pomieszania cytatów
Niektóre języki są językami kleju i kończą się na napisach w wielu różnych językach.
Na przykład JavaScript często składa się z ciągów HTML, CSS, XML, JSON, a nawet JavaScript. Bardzo trudno jest programistom pamiętać o prawidłowym kodowaniu ciągów tekstowych podczas ich łączenia w celu tworzenia ciągów w innych językach, więc programy JS, jak można się było spodziewać, mają wszelkiego rodzaju problemy z pomijaniem cytatów: XSS jest najgorszy.
Jeśli chcesz uwzględnić funkcje kompozycji ciągów, spróbuj zmniejszyć obciążenie programisty. DSL, higieniczne makra i osadzone języki szablonów mogą być świetnym sposobem na to, przenosząc ciężar prawidłowego ucieczki do twórców bibliotek lub języków z dala od programisty końcowego.