"I'm Launching Code from the Internet, What Will You Do to Me?" - On the Safe Use of JS Packages (film, 40 minutes)
During the recent conference, Zbyszek from the PROIDEA Events channel gave a presentation about the dangers of using source code from the internet, especially in the context of JavaScript technology. He highlighted the problem faced by developers when it comes to using npm packages, many of which come from unknown authors and might contain malicious code. Using personal experiences, Zbyszek referred to past issues that arose from using packages with unknown security implications. He emphasized that many developers don't realize the risks associated with untrusted npm packages, which can lead to severe consequences such as data breaches.
Zbyszek also demonstrated an intriguing example where malicious code could be embedded in a project under the guise of a normal package. He focused on a phenomenon known as "dependency confusion," where malicious packages can slip into the dependency tree. Throughout the presentation, Zbyszek showcased protective techniques, such as application shielding policies, and mentioned that some of them are available through tools like Lava Mode. Lava Mode represents an innovative approach to safeguarding applications against malicious code and ensures unauthorized scripts do not run during package installation.
Moreover, Zbyszek cited specific cases of supply chain attacks, emphasizing that malicious packages would not get too far if developers implemented proper security techniques. At the end of the session, Zbyszek invited listeners to engage in a discussion about new approaches in application security. He stressed the need to remain vigilant and aware of potential threats arising from the use of external packages and malicious code. At the time of writing this article, the recording of his talk had already garnered 1411 views and 33 likes, indicating a significant interest in the topic.
Toggle timeline summary
-
Introduction of Zbyszek and the project.
-
A personal request from the chairman.
-
Passing the microphone to Zbyszek and distributing stickers.
-
Welcoming the speaker, Zbyszek.
-
Zbyszek begins to talk about using code from the internet.
-
He discusses JavaScript as a common coding language.
-
His early experiences with security and JavaScript.
-
Explains a crashing issue with Internet Explorer.
-
Questions about using code from the internet.
-
Discusses the risks of incorporating external code.
-
The importance of consuming packages from Node Modules.
-
Zbyszek shares his concerns about external code.
-
Contemplates the implications of trust in code.
-
Explains potential dangers of installing packages.
-
Asks what could go wrong with package installations.
-
Describes how malicious packages could exploit vulnerabilities.
-
Potential risks of calling external database functions.
-
Shares a story involving a Black Hat scenario.
-
Discusses the concept of 'dependency confusion'.
-
Explains creating a safe environment to test packages.
-
Shows a TypeScript application with a malicious package.
-
Demonstrating attempts to control access within code.
-
Discusses the importance of Secure ECMAScript.
-
Explains the concept of object capability security.
-
Details how to implement policies to block malicious code.
-
Discusses plans to enhance the language with new features.
-
Introduces Lava Mode as a tool for supply chain security.
-
Talks about protecting real-world applications against attacks.
-
Offers t-shirts for those who implement safety precautions.
-
Concludes his talk and thanks the audience.
Transcription
Więcej o sobie pewnie powie Zbyszek, o projekcie również. Padła też taka prośba osobista, którą chciałbym spełnić jako czermen. Przekażę mikrofon Zbyszkowi, a wam rozdam takie naklejki. W imieniu prelegenta bardzo proszę o ich przyjęcie. Powitajmy brawami naszego prelegenta Zbyszka. APLAUZ Cześć. Słychać mnie? Dobrze. To ja dzisiaj będę wam opowiadał o tym, jak wziąć kod z internetu i go odpalić i nie cierpieć konsekwencji tego. Więc może na początek... Kod z internetu, wiadomo, zwykle będzie to JavaScript. I troszeczkę o mnie. Skąd ja się tu wziąłem? Moje zamiłowanie do security w Javascript było zanim znałem się na Javascriptie albo Security, bo to jest pierwsze pięć linijek Javascriptu, jakie w życiu napisałem. Odpalenie tego w Explorerze na 9.8 albo XP kraszowało Explorera, ale nie tylko przeglądarkę, cały proces Explorera, także znikał też pulpit, pasek, wszystko. Zostało to naprawione w XP Service Pack 2. Skoro powiedziałem wam już o starym exploicie, który był trywialny i teraz wam smutno, że przyszliście do branży po tym, jak można było robić tak trywialne rzeczy, to to już jest prelekcja na konferencję o security. Mogę przejść dalej. Więc wiedząc to, co wam powiedziałem przed chwilą, czy gdybym wam dał napis, kawałek tekstu, czy włożylibyście go do swojej aplikacji i uruchomili? Jesteś chętni? Nie? Nie chcecie mojego kodu? A gdybym spakował go w targie Zeta, pomogłoby? No właśnie, wydaje mi się, że tak, bo to są paczki NPM-owe i każdy, kto ma coś wspólnego z JavaScriptem, instaluje paczki NPM-owe, a to jest cudzy kod od obcych ludzi, których nie znacie, który ściągacie z internetu i odpalacie w ramach swojej aplikacji. W Buildzie, na produkcji, wszędzie. Czyli siedzimy sobie i konsumujemy te paczki. I ja też tak robiłem, jest to wspaniała rzecz, bardzo to lubię robić nadal, tylko mniej więcej w 2015 roku pierwszy raz zacząłem się zastanawiać, a co jeśli? No i okazuje się, wtedy trafiłem na informację, że w 2014 ktoś wpadł na pomysł, żeby zrobić paczkę, która będzie miała w sobie kod, który będzie szukał, czy w sąsiedztwie są inne foldery, w których jest package.json i będzie się tam roznosił ten kod i odpalał NPM Publish na wypadek, gdyby to były paczki, które można opublikować w imieniu autora, który właśnie coś ściągnął. Czyli taki worm roznoszący się po NPM-ie. To było w 2014 roku wymyślone i do dziś nikt tego nie zrobił. Nie wiem dlaczego, ale jest to miłe. Dobrze, ale co może pójść nie tak? Jeżeli instalujecie sobie paczki, to taka paczka może robić różne bardziej oczywiste rzeczy, ale z ciekawszych może wziąć kredenciale, które znajdzie w okolicy, np. w zmiennych środowiskowych, gdzie się je często umieszcza, i wysłać je gdzieś. Może znaleźć sąsiedni pakiet, który ma funkcjonalność dostępu do bazy danych, czyli wasza libka do klienta, do bazy danych. Wywołać stamtąd odpowiednią funkcję, zdumpować dane użytkowników, wysłać je gdzieś. Dlaczego nie? JavaScript. Odpalacie. Cały, taki sam. Więc co może pójść nie tak? Jeden z tych wielu pakietów, które zainstalowaliście w NodeModules, słynącym z tego, że jest największym folderem na dysku, może zawierać coś nieprzyjemnego i jak to wychwycić. Opowiem wam małą historyjkę, a w zasadzie odegram, w której będzie występował Black Hat, reprezentowany przez obrazek oraz Black Hat. I programista, taki jak ja, przez większość swojej kariery byłem programistą JavaScriptu, tylko się interesowałem tym bezpieczeństwem jakoś tak namolnie. I tak jakoś wyszło. Dobrze, więc no to co? Zainstalujmy sobie jakieś zależności. Mam projekt, instaluję sobie całe drzewo zależności skądś. No, na tym polega moja praca. No dobra, to łap to. To ja ci wrzucę jakąś paczkę, gdzieś głęboko w twoim łańcuchu zależności znajdę coś, co jest już trochę nieutrzymywane. Może coś tam dam radę dorzucić albo jakiś dependency confusion, jeżeli ktoś zna, bardzo nudny temat, nie opowiadam o tym z premedytacją, ale ważny. Dobrze, że jest Lilan Tal, który to robi. Okej, no ale ja tego nie uruchomię przecież. Jak nie wiem nawet o paczce, którą mi podrzuciłeś, to ja tego nie uruchomię. Dlaczego miałbym? Nie wywołam tej paczki, nie zrobię na niej require, prawda? No nieprawda. A wiesz o tym, że jest coś takie jak life cycle w krypcji? Mogę w packet.json mojej paczki napisać post install dwukropek i tam wprowadzić dowolny kod, który zostanie uruchomiony, tak jakbym jako ty wpisał go do terminala. No dobra, a gdyby tak... I to jest autentyczny przykład czegoś, co zrobiłem koło 2016 roku. Skoro nie ufam do końca intencjom ludzi, których paczki instaluję, to ja bym sobie odpalił kontener, taki pusty, w którym nie ma nic wartościowego, odpalił tam, używając tylko mojego package locka, odpalił tam npmci, żeby zainstalować te zależności, skopiuję te zależności gdzieś na zewnętrzny storage i zniszczę cały system, żeby nic się nie dało z tym zrobić. No to co mi zrobisz? A używasz może typescriptu? Skoro tak, no to spróbujmy. A, nie, to muszę zostawić. I wyglądałoby to tak. Nie, tego wam nie miałem pokazywać, miałem wam pokazać to. Mam przykładową aplikację, w której jest taki packet json, w którym jest typescript i jest moja złośliwa paczka. Chyba wystarczająco duży jest ten tekst, co? No i mamy aplikację napisaną w typescriptie, uwaga. Typescript jest nadzbiorem javascriptu, więc to jest poprawny typescript. Jakby ktoś miał wątpliwości. Aplikacja jest celowo tak zaawansowana, żeby nie było trudno jej przeanalizować. To jest cała aplikacja. Nie ma tu żadnych innych plików, jest tylko ten jeden. OK, no to teraz w tej aplikacji robimy sobie, mam nadzieję, że hotelowe Wi-Fi mi nie przeszkodzi. Robimy sobie instalację na czysto. OK, zainstalowały mi się paczki. Nic się nie wydarzyło, nic się nie zmieniło. Chyba jest wszystko dobrze. Mam apkę, dobrze. No to mój pakiet JSON zawiera komendę start, która buduje aplikację. Odpalmy to. Zbudowało się. Mamy app.js, prawda? Czy ktoś z Was zagląda do javascriptu, który Wam się zbuduje z typescriptu? Ręka do góry. Wow, pierwszy raz zobaczyłem podnoszące się ręce. No to dobrze, że zaglądacie, bo mi się coś nie zgadza. Tak na szybko, co to jest? Komentarz na początku, bo nie mogłem się powstrzymać. Później w trycatchu coś dla użytkowników nouda, czyli zapisuję do pliku cały environment. Równie dobrze mogłem go wysyłać gdzieś na serwer, nieważne. Drugi element dla kogoś, kto robi w przeglądarce. Przekazujemy do Evala to, co jest w haszu adresu, czyli najkrótszy możliwy Reflected XSS. I znalazł się w kodzie zbudowanej aplikacji. Ta paczka to zabawka, którą zrobiłem trzy lata temu w dwa wieczory. Trochę trzeba się było pobawić, żeby w skompilowanym kompilatorze typescriptu umieścić coś, co doda złośliwy kod do aplikacji. Potem zabrałem się za wymyślanie sposobu, żeby to powstrzymać, co doprowadziło mnie do mojej obecnej pracy. To długa historia. Wracamy do naszej stenki. OK, to ja mam taki pomysł, że ja w takim razie użyję opcji, żeby w ogóle zignorować wszystkie postinstale. NPM i Jarn mają taką opcję, żeby to wyłączyć. Jest taki drobny kłopot, że jak to wyłączę, to paczki, które potrzebują się zbudować, nie chcą działać. No to ja bym je zbudował osobno. Czyli mam paczki, którym ufam, które potrzebują postinstala, więc jak odpalę sobie npm rebuild bcrypt, to moduł o nazwie bcrypt zostanie przebudowany, a pozostałe nie. Moduł o nazwie bcrypt, powiadasz? No dobrze, to ja też mogę mieć moduł o nazwie bcrypt. Bo dlaczego nie? O tym mogliście nie wiedzieć. Jeżeli mamy paczkę na npm, to ta paczka w swoim targie Z w środku może mieć folder node modules, w którym znajdują się jej zależności, które się nazywają bundled dependencies. I npm już nie ma wglądów w to, jak się będą nazywać, więc nazwa może być dowolna. Zarówno klient npm-owy, jak i jarnowy wierzy w te nazwy. W związku z tym teraz, jak odpalimy npm rebuild bcrypt, mam na to demo, możemy zrobić na końcu, zobaczymy, czy wystarczy czasu, to odpali build oryginalnego bcrypta i mojego bcrypta. No, co teraz? No znalazłem takie coś. Nazywa się to lavamode, taką nalepkę każdy z was już ma. Jeżeli ktoś przyszedł i nie ma nalepki, to tutaj siedzi człowiek, który wam ją chętnie udzieli, albo można do mnie podejść później. Lavamode to jest, coś przy czym teraz pracuję, narzędzie zupełnie open source, dostępne dla każdego nieodpłatnie, bez żadnych zobowiązań, które zawiera w sobie kilka różnych tool do tego, żeby zabezpieczać się przed atakami typu supply chain. No i pierwszym z nich, o którym sobie powiemy, a jest potrzebny, jest lavamode allowscripts. Mamy tutaj polecenie, allowscripts, odpalamy setup, zostaje skonfigurowane repozytorium, tak żebyście nie musieli używać już przełączników przy instalowaniu. Powstaje plik konfiguracyjny, który odpowiednio dla NPM-a czy YARN-a zawiera konfigurację wyłączającą skrypty i później robimy allowscripts auto, co nam generuje whitelistę tego, co możemy spośród tych skryptów odpalać. No i wtedy dopisujemy sobie do pakiet.json setup, który polega na odpaleniu już samego NPM-ci i później allowscripts, allowscripts bez parametru, odpali nam tylko i wyłącznie dozwolone post installe i tak dalej, tylko i wyłącznie z precyzyjnie wskazanych paczek. Nie po nazwie, ale po całej ścieżce w drzewie zależności. No dobra, to to się nie udało, ale widzę, że masz pole skrypts w pakiet.json, no to może odpalasz tam skrypty poprzez napisanie NPM coś tam albo node coś tam. I tutaj oczywiście kredyt, jest coś takiego jak socket security, socket.dev, polecam używać oprócz lavamode zamiast wielu innych rzeczy. Można się dużo dowiedzieć o swoich zależnościach. Oni opublikowali taką fajną sztuczkę. Nie wiem, czy wiecie, każda paczka na NPM-ie może deklarować w pakiet.json, że zawiera w sobie komendy. Na przykład taki typescript definiuje komendę tsc, którą możemy sobie odpalić dzięki temu wewnątrz swojego projektu. Ale nikt nie mówi, że ta komenda nie może się nazywać NPM albo node. Na to też jest fajne demko i może Wam je pokażę. Mamy tutaj aplikację, której jedyną zależnością jest NPM bin script POC. To jest opublikowane na NPM-ie, bo NPM nie uznał tego za wystarczająco złośliwe, żeby zablokować konto temu, kto to opublikował. Tak jak mi kiedyś wcześniej za opublikowanie czegoś złośliwego na NPM-ie. No dobra, niech mu będzie. I teraz wchodzimy do folderu z tą apką. No i samo odpalenie procesu instalacyjnego tu nic nie robi, ale jak widzicie, mam polecenie test, polecenie build, więc jeżeli odpalę sobie NPM test, to odpala mi się przeglądarka. Nie będę teraz tego odpalał, musicie mi uwierzyć na słowo, że jest tam wideo z panem o imieniu Rick, który śpiewa i tańczy. No i jak się przed tym powstrzymać? Otóż NPM mówi, że to jest feature i nie można tego zepsuć. Więc oficjalną drogą się przed tym nie obronimy, ale jeżeli przeczytam do końca read me w paczce allow scripts z zestawu narzędzi lava mode, to znajdę tam eksperymentalny nowy feature, który za chwilę będzie opublikowany, który w ten sam sposób, w jaki kontrolował skrypty post install, kontroluje również to, jakie rzeczy są linkowane spośród waszych zależności jako komendy, które można wywoływać i dostajecie pełną kontrolę nad tym, co tam jest, jeżeli cokolwiek się zmieni, to nie zostanie zainstalowane. Czyli jeżeli jakaś paczka nagle postanowi, że oprócz TSC będzie jeszcze wystawiać komendę NPM albo node, to się w ogóle nie zainstaluje. Macie pełną kontrolę nad tym, co to będzie. Nawet gdyby ktoś postanowił, że jego paczka będzie miała komendę o nazwie RM, to też będziecie bronieni. Tam jest taki jakby firewall, fajna sprawa. Niedługo będzie można wypróbować. No dobrze. No ale NPM mówił, że to feature. No jak można to zepsuć? Okej. To proste triki mi się skończyły. Trzeba się zabrać za to na poważnie. A jeżeli robimy coś poważnie, to znaczy, że przez maila. Dobrze. To napiszę do różnych maintainerów, różnych pluginów do ES-linta, że ja bardzo cenię ich czas i chciałbym im pomóc. Może ktoś się zgodzi. A jak już się zgodzi, to wrzucę tam takie coś. Okej. No i co ty na to, deweloperze? Będziesz czytał wszystko, co masz w node modules? No dobra, jestem na konferencji o security, więc może ktoś czyta. Okej. No to na wypadek, gdybyś czytał, może to zobfuskujemy troszkę. Ale tu jest jeszcze nadal napisane GitHub token i HTTPS. Mogę iść dalej. To jest screenshot z obfuskacji. Ten sam kod po obfuskacji ma co prawda 70 kilobajtów, ale człowiek go już nie przeczyta. Nawet narzędzia do deobfuskacji go nie bardzo przeczytają, bo jest tutaj dużo rzeczy do danych typu pętla nieskończona, jeżeli ten kod zostanie uruchomiony z deobfuskowanej postaci. Bawiłem się czymś takim niedawno zresztą. Lofi gang. Jeśli ktoś chciałby sample, to jeszcze są nawet na npm-ie dostępne. Okej. Więc to mam do tego apkę, bo Lava Mode tak naprawdę, główny feature Lava Mode, to ochrona w runtime. Co robimy? Generujemy sobie policy, czyli odpalamy nasz kod razem z jego zależnościami. Poleceniem Lava Mode z opcją auto to nam wygeneruje automatycznie politykę. Przeanalizuje cały kod, jaki uruchomiłby się i wyciągnie z tego wszystkie rzeczy, które wydają się niezbędne do jego działania. Jeżeli coś jest zobfuskowane, to pewnie tego nie zauważy, ale w runtime, kiedy odpalimy sobie to akurat na CI odpalamy sobie build przez Lava Mode. Pod spodem jest oczywiście node, ale z pewnymi rzeczami zrobionymi w javascriptie, które blokują możliwość wykonania rzeczy, które korzystają z dostępów do czegoś, czego nie używały wcześniej, kiedy wygenerowaliśmy policy. I to policy można oczywiście kontrolować. Takie policy wygląda jego fragment mniej więcej tak. Zakładając, że przeczytaliśmy co nasz plugin robi, bo nie był mocno zobfuskowany, to mamy tutaj z jakich built-inów korzysta, z jakich globali korzysta. No i teraz to, co ja mogę zrobić, to zabronić. Jeżeli coś nie zostało zauważone, jest z automatu traktowane jako falsie. I teraz jeżeli odpalimy z takim policy nasz build, w którym jest ten nowy złośliwy kod, dostaniemy jeden z tych błędów. Otóż Evil Dependency próbowało wczytać paczkę HTTPS, w sensie internala HTTPS przez require, a my się na to nie zgadzaliśmy, więc to jest błąd, który zatrzymuje wszystko. Inny błąd, type error. Próbowaliśmy odczytać ends undefined. Nie ma czegoś takiego jak proces. Ta paczka widzi globale, w których nie ma słowa proces. Ale jak? No cóż. I tutaj już wchodzimy bez czepeczki, bo trzeba porozmawiać o tym, co jest w środku. LavaMode jest narzędziem zbudowanym na pewnym projekcie, który się nazywa SES, w skrót od Secure ECMAScript, chociaż autorzy powoli chcą go przebrandować na Hardened JavaScript. I to, co robi LavaMode, to używa SES do tego, żeby spakować każdą paczkę w waszych zależnościach do osobnego pudełeczka, który się nazywa kompartment. I to się dzieje w runtime, używa feature'ów JavaScriptu i umożliwia kontrolowanie, co dana paczka będzie widziała jako globale, kontrolowanie, co dana paczka będzie mogła importować. I to nie jest jakiś wymysł, który poistnieje sobie chwilę i zniknie, bo Secure ECMAScript został wymyślony przez ludzi, którzy są w TC39 i ich długoterminowym planem jest wprowadzenie kompartmentów do języka. Jest proposal, ten stary proposal ma opis wszystkiego lekko nieaktualny, ten nowy proposal ma opis pewnego podzbioru i będzie wprowadzany krokami różne feature'y, jeden to silniejszy jeśli chodzi o możliwości, jakie daje, aż dojdziemy do pełnej kompartmentalizacji. Mój poprzedni talk, który możecie zobaczyć na mojej stronie www.nauktur.pl. Generalnie jak wpiszecie Nauk Tur w jakieś pole tekstowe i będzie z tego jakiś wynik, to to jest coś związanego ze mną. W poprzedniej mojej prelekcji są szczegóły tego, jak to działa w środku. Tutaj opowiem wam tak bardziej z perspektywy, co to osiąga i co jest w środku, bo to nie jest istotne. Jak to się znajdzie w języku, to nas nie będzie interesowało, co jest w środku, tylko to, że specyfikacja języka gwarantuje, że to musi działać. Na to musimy jeszcze poczekać pewnie ze 2-3 lata, ale taki jest plan. Pomysłodawcą SES jest facet, który wprowadził do Javascriptu takie rzeczy jak use strict, object freeze i wprowadził je obie z intencją zbudowania tego. A było to dosyć dawno, także to jest long game i to sobie nie pójdzie, tylko będzie się rozwijać. A to wszystko po to, żeby móc używać w Javascriptie nowego paradygmatu programowania, object capability, zamiast opierać się na identity-based security. Identity-based security to jest to, co w programowaniu znacie, czyli jeżeli coś chce dostępu do jakiegoś silnego API, do czegoś, co może robić rzeczy dobre i złe, to musi się do tego jakoś dostać. Obecnie sprawdzamy, kto próbuje to wykonać. I teraz jak zrobicie sobie node spacja app.js, to cały kod w app.js działa jako wasz użytkownik, który odpalił to w terminalu, czyli on behalf of, zasada aplikuje się do użytkownika i w imieniu tego użytkownika można robić wszystko, na przykład jeśli to był root, no to absolutnie wszystko, a jeśli nie, to trochę mniej. Ale nadal grzebać po dysku i tak dalej. Natomiast object capability polega na tym, że wewnątrz w programie przekazujemy uprawnienia przez referencje, tak jak dane. Uprawnienia są tym samym co dane. Gadałem długo, a wygląda to tak. Jeżeli mamy jakiś linter i ten linter chce dostępu do plików, ale ma tylko je sprawdzić, a nie je modyfikować, to możemy mu dać do dyspozycji podzbiór całej możliwości dostępu do systemu plików. Czyli już w programie mamy możliwość ograniczenia dostępu. Nie potrzebujemy dodatkowych metod wpinania się w to wszystko, kontrolowania tego, sprawdzania, kto w ogóle próbuje się do czegoś dostać, bo to już wiemy na poziomie kodu. No i Secure ECMAScript to jest ten element w javascriptzie, którego brakowało, żeby zrobić z niego język do object capability. Mamy tam kompartment, czyli możliwość odizolowania kodu od stanu globalnego i od wszystkich pozostałych kompartmentów. Mamy lockdown, który naprawia różne niedociągnięcia w javascriptzie pozwalające na przykład na prototype pollution. Lockdown używa object freeze do tego, żeby zablokować wszystko, co mogłoby być niebezpieczne. I w ten sposób rzeczy w dwóch różnych kompartmentach nie mogą zmodyfikować sobie globalnego prototypu, tak żeby na siebie wpłynąć. Jest jeszcze harden, żeby zabezpieczyć fragmenty waszego programu przekazywane do środka kompartmentu, w którym działa coś innego. I to są te trzy podstawowe klocki, z których budujemy. I okazuje się, że to wystarczy. Bo javascript, nie będę twierdził, że zamierzenie, jest językiem, w którym... To nie ja. Jest językiem, w którym okazuje się, że zadziałało prawo Conwaya, ponieważ sam język jest standardyzowany osobno od W3C czy ekipy, która robiła Noda. I wszystkie API, które dają dostęp do czegokolwiek, są poza standardem javascriptu. Decydują o nich inni ludzie. Prawo Conwaya mówi, że organizacja odwzorowuje w softwareze strukturę komunikacyjną swoją. Więc połączenie z języka do jego silnych możliwości w javascriptie jest bardzo wąskim gardłem, bo jedyny sposób, w jaki można zdobyć coś, czym możecie wpływać na otoczenie, inaczej niż zużywając cykle procesora, jest albo przez globalny scope, no bo jest window.fetch na przykład, albo przez zaimportowanie czegoś, co jest internalem w Nodzie, ewentualnie w jakimś innym środowisku. No i tam przychodzi kompartment, który to wszystko kontroluje i nie da się już zrobić nic z dostępem do dysku, z dostępem do sieci, jeżeli ta moc nie została nadana z góry. I to jest hardened javascript. No OK, było tego dużo. Podsumowanie. Czyli w lava mode mamy allow scripts, które bronią nas podczas instalacji. Mamy ochronę podczas builda, która polega na tym, że nie działają złośliwe komendy, które ktoś mógł dołożyć oraz mamy runtime protection, które się przydaje i w buildzie, w Nodzie i później przy uruchamianiu tego albo aplikacji serwerowej w javascriptie, albo przeglądarkowej, gdzie złośliwy kod, który nagle postanowi sięgnąć do networku, a ta paczka nigdy wcześniej tego nie robiła, zostanie zablokowany. No i to wszystko jest zrobione przy użyciu hardened javascript. Jak tego użyć? Mamy parę opcji. Można wziąć ses i używać go bezpośrednio. Jeżeli potrzebujecie zbudować funkcjonalność produkt oparty na idei uruchamiania cudzego niezaufanego kodu w waszym procesie, w waszym wątku javascriptowym, wewnątrz waszej ramki w przeglądarce, możecie to zrobić, używając ses i lockdown. Jeżeli chcecie trochę więcej, jest zestaw narzędzi budowany dookoła ses, jeszcze nie do końca gotowy, nazywa się endo, jeśli ktoś nie złapał żartu, był node, później było deno, następny jest endo. Jest tam kompartment mapper, od którego warto zacząć. To jest coś, na czym następna duża wersja Lava Mode będzie zbudowana, bo wiele feature'ów, których potrzebujemy, teraz wprowadzamy tam. I jest Lava Mode, który służy konkretnie do jednego zastosowania supply chain security w oparciu o powyższe. No i Lava Mode w tej chwili od miesięcy, prawie roku, chroni metamask, może słyszeliście taki portfelik do takich śmiesznych cyfrowych coinów, używany przez jakieś 30 milionów użytkowników. W tej chwili metamask jest broniony przez Lava Mode na wszystkich poziomach przed atakami supply chain security, no bo trochę nie mogliśmy sobie pozwolić na to, że dowiadujemy się, że jakaś paczka jest złośliwa z npm audit albo z monitorowania sieci, że było jakieś niespodziewane połączenie wychodzące z naszej aplikacji, bo wtedy jest już za późno. Więc cała idea Lava Mode była taka, żeby powstrzymać rzeczy przed uruchomieniem się. Jeżeli złośliwy kod trafił już do aplikacji, uruchamia się u użytkownika. Jeżeli ktoś chce wiedzieć więcej, ta prezentacja na nauktor.pl, pierwsza na liście prezentacji. Tutaj macie link do mojego wcześniejszego wystąpienia po angielsku, linki na liście prezentacji i wystąpienie Marka Millera, najświeższe. Mark Miller jest tym pomysłodawcą SES, jak również tego, co znamy jako ECMAScript 5 razem z Douglasem Crockfordem, jeśli ktoś nie wiedział. I zbliżam się do końca. Jeżeli ktoś by chciał pomocy przy zastosowaniu Lava Mode w swoim projekcie, to można się do mnie odzywać, bo chciałbym mieć trochę use case'ów, które są ze świata, żeby mieć dużo różnych przypadków, móc się dowiedzieć, co zadziałało, co nie zadziałało, jakie przypadki jeszcze trzeba obsłużyć. Tak że zachęcam do kontaktowania się. No i trzeba by sprawdzić, ile zostało nam czasu. 12 minut. OK, to mamy czas na różne inne fajne demka. To zaczniemy od tego, żeby zobaczyć Lava Mode w akcji. Dobrze, mam tutaj pakiet JSON. To jest aplikacja. Ta aplikacja nie robi nic mądrego, ale przynajmniej coś robi. Jeżeli ją odpalam, to ona używa swojej zależności do tego, żeby na podstawie bufora zawierającego dużą liczbę wygenerować wierszyk. Od wierszyk. Dobrze. Teraz mam tutaj też zainstalowaną złośliwą paczkę. I uwaga, ta złośliwa paczka jest odpowiedzialna za dostarczenie tego feature'a. No i odpalamy sobie Lava Mode Auto. Autopolicy rozwinąłem w całości, żeby było ładniej. I tu się generuje policy JSON. A, właśnie, muszę to jeszcze odpalić. Dla większej aplikacji trwałoby to dłużej. No i mamy tutaj całe policy. Evil Sample to jest moja paczka, która korzysta z Entropoetry, która korzysta z Big Number JS. Big Number JS używa buforów, które bierze zarówno z Globala, jak i przez Require, bo czemu nie. Samo Entropoetry korzysta z paru drobnych rzeczy, żeby wygenerować ten wierszyk z liczb. No i paczka Evil Sample tak naprawdę tylko dostarcza do mojej aplikacji tą funkcjonalność, przy czym wygląda to tak. Zaciągam sobie to jako zależność, odpalam funkcje i gotowe. Więc odpalam cudzy kod, który coś robi, na czym mi zależy. No dobrze. No to teraz ten ktoś zmienił zdanie na temat swoich intencji co do mnie i w następnej wersji tej paczki, którą musimy teraz sobie doinstalować. Mam nadzieję, że się udało. Czy package.log to już ma? A dobra. Przetestujemy to po prostu. Mamy app.js i sobie odpalimy. I tam była taka pauza na końcu, dość charakterystyczna. Myślę, że to to. Jak zajrzymy do kodu Evil Sample, to wersja 1.0.1 zawiera jeszcze takie coś. Robi takie zapytanie. Mogę zrobić jeszcze npm ls i zobaczymy sobie Evil Sample. Tak, jest wersja 1.0.1. Wspaniale. I teraz chciałbym, żeby ten kod się nie odpalał, ale mam już wygenerowaną politykę, w której nie ma mowy o dostępie do sieci. W związku z tym mogę teraz odpalić. Mam do tego skrót tutaj. Mogę odpalić aplikację przez Lava Mode. Boom. Dostałem błąd, który mówi, że package Evil Sample requested HTTPS, a nie było tego w polityce. No to nieładnie. OK. A co jeżeli on potrzebował tego? No możemy zrobić nową politykę. I tutaj mamy już HTTPS request. Mamy process end. I o ile wysyłanie zapytań potrzebujemy, żeby ta paczka robiła, ale nie chcemy, żeby miała dostęp do tego. To teraz już... Nie to, nie to. Stop. Jeszcze raz. Teraz już nie dostaniemy błędu o HTTPS-ie, tylko dostaniemy błąd, który mówi... Ups. Który mówi, że coś nie wyszło. Dobrze, to ja to usunę po prostu. Pewnie zrobiłem gdzieś literówkę, nie chce mi się rzucać. OK. No już nie ma czegoś takiego proces, więc nie ma z czego odczytać end. Jesteśmy w domu. Aplikacja jest bezpieczna, niezależnie od tego, co ta złośliwa paczka próbuje zrobić poza uprawnieniami, które jej przydzieliliśmy tej konkretnej paczce. I tak dowolnie głęboko w waszym drzewie zależności to wszystko wygenerowane przez automat z nielicznymi poprawkami z waszej strony i możliwością review w repozytorium kodu. Ile nam teraz zostało czasu? Siedem. OK. To całego dema wam już nie pokażę, ale mam jeszcze jeden bonus, bo Secure ECMAScript ma dużo różnych fajnych zastosowań i zrobiłem sobie niedawno taki eksperyment. Znowu, kto słyszał o Lofi Gang? A fajna sprawa. Nie pamiętam adresu. Lofi Gang Info. To jest stronka, która opisuje ten atak. 200 paczek na NPM-ie ze złośliwym kodem. Kod obfuskowany czterokrotnie. Przez cztery warstwy obfuskacji trzeba było przejść, żeby dostać goły kod, który w dodatku zawierał różne triki typu pętle nieskończone, które się odpalają tylko jeżeli kod funkcji nie jest obfuskowany, tylko już odczytany. I próbowałem przez to dla sportu przebrnąć ręcznie. Ściągnąłem sobie jeden sample. O, tu są jeszcze pojedyncze, których nie usunięto z NPM-a z jakiegoś powodu. Ściągnąłem sobie jeden taki sample. Zacząłem w nim grzebać, a potem stwierdziłem, że po co ja to deobfuskuję, jeżeli mam kontrolę w runtime'ie nad tym, co się uruchamia. Więc następny krok wyglądał tak, że spakowałem ten kod do kompartmentu. Na wszelki wypadek odpaliłem to w kontenerze bez dostępu do Internetu, ale nie było to konieczne. I dodałem jedną rzecz. Zamiast polityki, która decyduje, co można odpalić, a co nie, zrobiłem sobie fragment kodu, który synchronicznie się pytał, co w tej sytuacji zrobić. I mam tutaj zapis z dużo prostszego przypadku. Kawałka kodu. I z tego możemy sobie odczytać, co ten kawałek kodu robił. Pierwsze, co? Próbował się dostać do Globala o nazwie konsol. No to się zgodziłem. Wypisał, this is a demo sample. Później próbował się dostać do Globala o nazwie URL. No to się zgodziłem. Coś tam sobie jakiś URL złożył z tekstu. Później próbował się dostać do Globala o nazwie require. To się nie zgodziłem. I zwróciłem require jako funkcję. Interfejs jeszcze może nie jest idealny, ale działa. No i wywołano require z argumentem fs. No dobra, fajnie. Ale ja nie chcę dać mu fsa, więc zwróciłem mu proxy. Później z tego, co zwróciłem z require, wywołano read file sync. Czy ja chcę to udostępnić? No nie. Zwróciłem nic. Nie zadziałało. I ostatnia próba. Był tam jakiś ewal z jakimś tekstem, czyli jakiś payload powiedzmy. Czy chcę odpalić to w prawdziwym ewal? No nie. Więc zamiast ewal poleciało console.log i cały payload został wypisany. I to jest jedno przejście przez krótki programik, który chyba jeszcze gdzieś tu mam. O, to było to. No i wywołanie read file sync się nie udało, bo się nie zgodziłem, więc zamiast a do ewala przeszło example payload. I to jest eksperyment, który jest na moim githubie dostępny, jakby ktoś się chciał pobawić. Nie polecam używania tego na poważnie póki co, bo wiedziałbym jak to obejść, ale większość malwareu powinno się dać tym przeanalizować i ja sobie będę nad tym hobbystycznie pracował. To taka ciekawostka. Aha, ostatnia rzecz. Zachęcam do zainstalowania sobie lava mode w swoim repozytorium. Jeśli mnie dzisiaj złapiecie z projektem, w którym macie wdrożone przynajmniej allow scripts, to ja tutaj mam t-shirty z logo lava mode i będę rozdawał. No i oczywiście oferuję też pomoc, tylko że to już poza konkursem. T-shirty były drukowane w Kolumbii i chwyciłem parę, jak się widziałem z kolegami z pracy. Oni akurat byli na konferencji, potrzebowali t-shirtów, także jeśli ktoś wygra t-shirt, proszę nie lizać na druku przed pierwszym praniem. To wszystko, co miałem. Dziękuję.