Pamięć cienia

https://chacker.pl/

Do tej pory pokazałem, że moduły śledzenia skażeń mogą śledzić skażenie dla każdego rejestru lub bajtu pamięci, ale nie wyjaśniłem jeszcze, gdzie przechowują informacje o skażeniach. Aby przechowywać informacje o tym, które części rejestrów lub pamięci są skażone i jakim kolorem, silniki DTA utrzymują dedykowaną pamięć cienia. Pamięć cienia to obszar pamięci wirtualnej przydzielony przez system DTA w celu śledzenia stanu skażenia pozostałej części pamięci. Zazwyczaj systemy DTA przydzielają również specjalną strukturę w pamięci, w której śledzą informacje o skażeniach dla rejestrów procesora. Struktura pamięci cienia różni się w zależności od ziarnistości skażenia i liczby obsługiwanych kolorów skażenia. Rysunek przedstawia przykładowe układy pamięci cienia o ziarnistości bajtowej do śledzenia odpowiednio do 1, 8 lub 32 kolorów na bajt pamięci.

Lewa część rysunku przedstawia pamięć wirtualną programu uruchomionego z DTA. Dokładniej, przedstawia zawartość czterech bajtów pamięci wirtualnej, oznaczonych jako A, B, C i D. Razem bajty te przechowują przykładową wartość szesnastkową 0xde8a421f.

Zależności sterowania

https://chacker.pl/

Przypomnijmy, że śledzenie skażeń służy do śledzenia przepływów danych. Czasami jednak przepływy danych mogą być niejawnie modyfikowane przez struktury sterujące, takie jak rozgałęzienia w tzw. przepływie niejawnym. Na razie przyjrzyjmy się poniższemu przykładowi syntetycznemu:

var = 0;

while(cond–) var++;

W tym przypadku atakujący, który kontroluje warunek pętli cond, może określić wartość zmiennej var. Nazywa się to zależnością sterowania. Chociaż atakujący może kontrolować zmienną var za pomocą zmiennej cond, nie ma jawnego przepływu danych między tymi dwiema zmiennymi. W związku z tym systemy DTA, które śledzą tylko jawne przepływy danych, nie przechwycą tej zależności i pozostawią zmienną var nieskażoną, nawet jeśli cond jest skażona, co skutkuje niedostatecznym skażeniem. W niektórych badaniach próbowano rozwiązać ten problem, propagując skażenie z warunków rozgałęzień i pętli na operacje wykonywane z powodu rozgałęzienia lub pętli. W tym przykładzie oznaczałoby to propagację skażenia z cond do var. Niestety, takie podejście prowadzi do masowego nadmiernego skażenia, ponieważ skażone warunki rozgałęzienia są powszechne, nawet jeśli nie ma ataku. Rozważmy na przykład następujące kontrole sanityzacji danych wprowadzanych przez użytkownika:

if(is_safe(user_input)) funcptr = safe_handler;

else

funcptr = error_handler;

Załóżmy, że skażamy wszystkie dane wprowadzane przez użytkownika, aby sprawdzić je pod kątem ataków, a skażenie user_input rozprzestrzenia się na wartość zwracaną przez funkcję is_safe, która jest używana jako warunek rozgałęzienia. Zakładając, że sanityzacja danych wprowadzanych przez użytkownika jest przeprowadzona poprawnie, listing jest całkowicie bezpieczny pomimo skażonego warunku rozgałęzienia. Jednak systemy DTA, które próbują śledzić zależności sterujące, nie potrafią odróżnić tej sytuacji od niebezpiecznej, pokazanej na poprzednim listingu.

Te systemy zawsze będą skaziły funcptr, wskaźnik do funkcji, który wskazuje na procedurę obsługi danych wprowadzanych przez użytkownika. Może to powodować fałszywe alarmy, gdy później zostanie wywołany zanieczyszczony funcptr. Takie częste fałszywe alarmy mogą całkowicie uniemożliwić korzystanie z systemu. Ponieważ rozgałęzienia na danych wprowadzanych przez użytkownika są powszechne, a niejawne przepływy, z których może skorzystać atakujący, są stosunkowo rzadkie, większość systemów DTA w praktyce nie śledzi zależności sterujących.

Nadmierne i niedomierne skażenie

https://chacker.pl/

W zależności od polityki skażenia, system DTA może cierpieć na niedomierne skażenie, nadmierne skażenie lub oba te zjawiska. Niedomierne skażenie występuje, gdy wartość nie jest skażona, mimo że „powinna być”, co w naszym przypadku oznacza, że ​​atakujący może bezkarnie wpłynąć na tę wartość bez wiedzy użytkownika. Niedomierne skażenie może być wynikiem polityki skażenia, na przykład jeśli system nie obsługuje dodatkowo przypadków skrajnych, takich jak bity przepełnienia, jak wspomniano wcześniej. Może to również wystąpić, gdy skażenie przepływa przez nieobsługiwane instrukcje, dla których nie istnieje mechanizm obsługi propagacji skażenia. Na przykład biblioteki DTA, takie jak libdft, zazwyczaj nie mają wbudowanej obsługi instrukcji x86 MMX lub SSE, więc skażenie przepływające przez takie instrukcje może zostać utracone. Zależności sterujące również mogą powodować niedomierne skażenie, jak wkrótce zobaczysz.

Podobnie jak niedomierne skażenie, nadmierne skażenie oznacza, że ​​wartości zostają skażone, mimo że „nie powinny”. Prowadzi to do fałszywych alarmów, takich jak alerty, gdy nie ma faktycznego ataku. Podobnie jak w przypadku niedostatecznego skażenia, nadmierne skażenie może wynikać z polityki skażenia lub sposobu obsługi zależności kontroli. Chociaż systemy DTA dążą do minimalizacji niedostatecznego i nadmiernego skażenia, generalnie niemożliwe jest całkowite uniknięcie tych problemów przy jednoczesnym zachowaniu rozsądnej wydajności. Obecnie nie ma praktycznej biblioteki DTA, która nie byłaby narażona na niedostateczne lub nadmierne skażenie.

Zasady propagacji skażenia

https://chacker.pl/

Zasada propagacji skażenia systemu DTA opisuje sposób, w jaki system propaguje skażenie i łączy kolory skażenia, jeśli wiele przepływów skażenia przebiega jednocześnie. Tabela 10-1 pokazuje, jak skażenie rozprzestrzenia się przez kilka różnych operacji w przykładowej zasadzie propagacji skażenia dla systemu DTA z dokładnością do bajtów i dwoma kolorami: „czerwonym” (R) i „niebieskim” (B). Wszystkie operandy w przykładach składają się z 4 bajtów. Należy pamiętać, że możliwe są inne zasady propagacji skażenia, szczególnie w przypadku złożonych operacji, które wykonują nieliniowe transformacje na swoich operandach.

Przykłady propagacji skażenia dla systemu DTA o granularności bajtów z dwoma kolorami: czerwonym (R) i niebieskim (B)

W pierwszym przykładzie wartość zmiennej a jest przypisywana zmiennej c (1), co odpowiada instrukcji mov x86. W przypadku prostych operacji, takich jak ta, reguły propagacji skażenia są również proste: ponieważ wyjście c jest po prostu kopią a, informacja o skażeniu dla c jest kopią informacji o skażeniu a. Innymi słowy, operatorem scalania skażeń w tym przypadku jest :=, operator przypisania. Następnym przykładem jest operacja xor, c = a ⊕ b (2). W tym przypadku nie ma sensu po prostu przypisywać skażenia z jednego z operandów wejściowych do wyjścia, ponieważ wyjście zależy od obu wejść. Zamiast tego, powszechną strategią skażenia jest pobieranie sumy bajt po bajcie (∪) skażenia operandów wejściowych. Na przykład, najbardziej znaczący bajt pierwszego operandu jest skażony na czerwono (R), a w drugim operandzie na niebiesko (B). Zatem skazą najbardziej znaczącego bajtu wyjściowego jest suma tych bajtów, oznaczonych kolorem czerwonym i niebieskim (RB). Ta sama polityka sumowania bajt po bajcie jest stosowana do dodawania w trzecim przykładzie (3). Należy zauważyć, że w przypadku dodawania istnieje przypadek skrajny: dodanie 2 bajtów może spowodować przepełnienie bitu, który przepływa do najmniej znaczącego bitu (LSB) sąsiedniego bajtu. Załóżmy, że atakujący kontroluje tylko najmniej znaczący bajt jednego z operandów. Wówczas, w tym przypadku skrajnym, atakujący może spowodować przepełnienie 1 bitu do sąsiedniego bajtu, co pozwoli mu również częściowo wpłynąć na wartość tego bajtu. Można uwzględnić ten przypadek skrajny w polityce skazy, dodając jawne sprawdzenie i skazując sąsiedni bajt w przypadku wystąpienia przepełnienia. W praktyce wiele systemów DTA nie sprawdza tego przypadku skrajnego, aby prostsza i szybsza propagacja skazy była łatwiejsza. Przykład (4) jest szczególnym przypadkiem operacji xor. Biorąc xor operandu z samym sobą (c = a ⊕ a) zawsze daje na wyjściu zero. W tym przypadku, nawet jeśli atakujący kontroluje a, nadal nie będzie miał kontroli nad wyjściem c. Polityka skażenia polega zatem na usunięciu skażenia każdego bajtu wyjściowego poprzez ustawienie go na zbiór pusty (∅). Następnie wykonuje się operację przesunięcia w lewo o stałą wartość, c = a ≪ 6 (5). Ponieważ drugi operand jest stały, atakujący nie zawsze może kontrolować wszystkie bajty wyjściowe, nawet jeśli częściowo kontroluje wejście a. Rozsądną polityką jest propagowanie skażenia wejściowego tylko do tych bajtów wyjścia, które są (częściowo lub całkowicie) pokryte jednym ze skażonych bajtów wejściowych, w efekcie „przesuwając skażenie w lewo”. W tym przykładzie, ponieważ atakujący kontroluje tylko dolny bajt a i jest on przesunięty w lewo o 6 bitów, oznacza to, że skażenie z dolnego bajtu rozprzestrzenia się na dwa dolne bajty wyjścia. Z drugiej strony, w przykładzie (6), zarówno wartość, która jest przesunięta (a), jak i wartość przesunięcia (b), są zmienne. Atakujący, który kontroluje b, jak w przykładzie, może wpłynąć na wszystkie bajty danych wyjściowych. W ten sposób skaza b jest przypisywana do każdego bajtu wyjściowego. Biblioteki DTA, takie jak libdft, mają predefiniowaną politykę skażenia, co oszczędza Ci kłopotu z implementacją reguł dla wszystkich typów instrukcji. Możesz jednak modyfikować reguły dla każdego narzędzia osobno, dla tych instrukcji, dla których domyślna polityka nie do końca odpowiada Twoim potrzebom. Na przykład, jeśli wdrażasz narzędzie przeznaczone do wykrywania wycieków informacji, możesz chcieć poprawić wydajność, wyłączając propagację skazy poprzez instrukcje, które zmieniają dane nie do poznania.

Kolory skażenia

https://chacker.pl/

We wszystkich dotychczasowych przykładach zakładaliśmy, że wartość jest skażona lub nie. Wracając do naszej analogii z rzeką, było to dość proste do zrobienia przy użyciu tylko jednego koloru barwnika. Czasami jednak może zaistnieć potrzeba jednoczesnego śledzenia wielu rzek przepływających przez ten sam system jaskiń. Jeśli zabarwisz wiele rzek tylko jednym kolorem, nie będziesz dokładnie wiedzieć, jak się one łączą, ponieważ zabarwiona woda może pochodzić z dowolnego źródła. Podobnie w systemach DTA czasami chcesz wiedzieć nie tylko, że wartość jest skażona, ale skąd pochodzi skażenie. Możesz użyć wielu kolorów skażenia, aby zastosować inny kolor do każdego źródła skażenia, tak aby po dotarciu skażenia do ujścia można było dokładnie określić, które źródło wpływa na ten ujścia. W systemie DTA z dokładnością do bajtów i tylko jednym kolorem skażenia, potrzebujesz tylko jednego bitu do śledzenia skażenia dla każdego bajtu pamięci. Aby obsługiwać więcej niż jeden kolor, musisz przechowywać więcej informacji o skażeniu na bajt. Na przykład, aby obsługiwać osiem kolorów, potrzebny jest 1 bajt informacji o skażeniu na bajt pamięci. Na pierwszy rzut oka można by pomyśleć, że w 1 bajcie informacji o skażeniu można zapisać 255 różnych kolorów, ponieważ jeden bajt może przechowywać 255 różnych wartości niezerowych. Jednak takie podejście nie pozwala na mieszanie różnych kolorów. Bez możliwości mieszania kolorów nie będzie można rozróżnić przepływów skażeń, gdy dwa przepływy skażeń działają razem: jeśli wartość jest dotknięta przez dwa różne źródła skażeń, każde z własnym kolorem, nie będzie można zarejestrować obu kolorów w informacjach o skażeniach dotkniętej wartości. Aby obsługiwać mieszanie kolorów, należy użyć dedykowanego bitu na kolor skażenia. Na przykład, jeśli masz 1 bajt informacji o skażeniu, możesz obsługiwać kolory 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 i 0x80. Następnie, jeśli konkretna wartość jest skażona zarówno kolorami 0x01, jak i 0x02, łączna informacja o skażeniu dla tej wartości wynosi 0x03, co jest bitowym OR dwóch kolorów. Możesz myśleć o różnych kolorach skażeń w kategoriach rzeczywistych kolorów, aby ułatwić sobie sprawę. Na przykład, możesz określić 0x01 jako „czerwony”, 0x02 jako „niebieski”, a połączony kolor 0x03 jako „fioletowy”.

Granularność skażenia

https://chacker.pl/

Granularność skażenia to jednostka informacji, za pomocą której system DTA śledzi skażenie. Na przykład, system bitowy śledzi, czy każdy pojedynczy bit w rejestrze lub pamięci jest skażony, podczas gdy system bajtowy śledzi informacje o skażeniu tylko dla każdego bajtu. Jeśli nawet 1 bit w danym bajcie jest skażony, system bajtowy oznaczy cały bajt jako skażony. Podobnie, w systemie słów, informacje o skażeniu są śledzone dla każdego słowa pamięci itd. Aby zobrazować różnicę między systemami DTA bitowymi a bajtowymi, rozważmy, jak skażenie rozprzestrzenia się poprzez operację bitową AND (&) na dwóch operandach o rozmiarze bajtu, z których jeden jest skażony. W poniższym przykładzie pokażę wszystkie bity każdego operandu osobno. Każdy bit jest otoczony polem. Białe pola reprezentują bity nieskażone, a szare bity skażone. Po pierwsze, oto jak skażenie rozprzestrzeniałoby się w systemie o dużej granularności bitowej:

Jak widać, wszystkie bity w pierwszym operandzie są skażone, podczas gdy w drugim operandzie nie ma żadnych bitów. Ponieważ jest to operacja bitowa AND, każdy bit wyjściowy może być ustawiony na 1 tylko wtedy, gdy oba operandy wejściowe mają wartość 1 na odpowiadającej im pozycji. Innymi słowy, jeśli atakujący kontroluje tylko pierwszy operand wejściowy, to jedynymi pozycjami bitów w wyjściu, na które może wpływać, są te, w których drugi operand ma wartość 1. Wszystkie pozostałe bity wyjściowe będą zawsze ustawione na 0. Dlatego w tym przykładzie tylko jeden bit wyjściowy jest skażony. Jest to jedyna pozycja bitowa, którą atakujący może kontrolować, ponieważ tylko ta pozycja jest ustawiona na 1 w drugim operandzie. W efekcie nieskażony drugi operand działa jak „filtr” skazy pierwszego operandu. Porównajmy to teraz z odpowiednią operacją w systemie DTA z granularnością bajtów. Dwa operandy wejściowe są takie same jak poprzednio.

Ponieważ system DTA z granularnością bajtową nie może rozpatrywać każdego bitu indywidualnie, całe wyjście jest oznaczane jako skażone. System po prostu widzi skażony bajt wejściowy i niezerowy drugi operand i dlatego wnioskuje, że atakujący może wpłynąć na operand wyjściowy. Jak widać, granularność systemu DTA jest ważnym czynnikiem wpływającym na jego dokładność: system z granularnością bajtową może być mniej dokładny niż system z granularnością bitową, w zależności od danych wejściowych. Z drugiej strony, granularność skażenia jest również ważnym czynnikiem wpływającym na wydajność systemu DTA. Kod instrumentacji wymagany do śledzenia skażenia indywidualnie dla każdego bitu jest złożony, co prowadzi do dużego obciążenia wydajności. Chociaż systemy z granularnością bajtową są mniej dokładne, pozwalają na prostsze reguły propagacji skażenia, wymagające jedynie prostego kodu instrumentacji. Ogólnie rzecz biorąc, oznacza to, że systemy z granularnością bajtową są znacznie szybsze niż systemy z granularnością bitową. W praktyce większość systemów DTA wykorzystuje granularność bajtową, aby osiągnąć rozsądny kompromis między dokładnością a szybkością.

Czynniki projektowe DTA: Granularność skażenia, kolory skażenia i zasady dotyczące skażenia

https://chacker.pl/

W poprzedniej sekcji DTA wymagało jedynie prostych reguł propagacji skażenia, a samo skażenie również było proste: bajt pamięci albo jest skażony, albo nie. W bardziej złożonych systemach DTA istnieje wiele czynników, które decydują o równowadze między wydajnością a wszechstronnością systemu. W tej sekcji poznasz trzy najważniejsze wymiary projektowe systemów DTA: granularność skażenia, liczbę kolorów i zasady dotyczące propagacji skażenia. Należy pamiętać, że DTA można wykorzystać do wielu różnych celów, w tym do wykrywania błędów, zapobiegania eksfiltracji danych, automatycznej optymalizacji kodu, analiz kryminalistycznych i innych. W każdym z tych zastosowań stwierdzenie, że wartość jest skażona, oznacza coś innego. Aby uprościć poniższą dyskusję, gdy wartość jest skażona, będę konsekwentnie interpretował to jako „atakujący może wpłynąć na tę wartość”.

Wykrywanie Heartbleed poprzez skażenie

https://chacker.pl/

Rysunek pokazuje, jak można użyć DTA do wykrycia tego rodzaju wycieku informacji, ilustrując to, co dzieje się w pamięci systemu atakowanego przez Heartbleed.

Na potrzeby tego przykładu można założyć, że żądanie Heartbeat jest przechowywane w pamięci w pobliżu klucza tajnego i że klucz tajny został skażony, aby można było śledzić, gdzie jest kopiowany. Można również założyć, że wywołania systemowe send i sendto są ujściami skażenia, wykrywając wszelkie skażone dane, które mają zostać wysłane przez sieć. Dla uproszczenia rysunek przedstawia tylko odpowiednie ciągi znaków w pamięci, ale nie pola typu i długości komunikatów żądania i odpowiedzi. Rysunek a przedstawia sytuację tuż po otrzymaniu żądania Heartbeat stworzonego przez atakującego. Żądanie zawiera ciąg danych foobar, który jest przechowywany w pamięci obok losowych bajtów (oznaczonych jako ?) i klucza tajnego. Zmienna pl wskazuje na początek ciągu, a atakujący ustawił ładunek na 21, tak aby 15 bajtów sąsiadujących z ciągiem ładunku zostało ujawnionych. Klucz tajny jest skażony, aby można było wykryć jego wyciek przez sieć, a bufor odpowiedzi jest przydzielany w innym miejscu pamięci. Następnie, rysunek b pokazuje, co się dzieje po uruchomieniu podatnego na ataki programu memcpy. Zgodnie z oczekiwaniami, program memcpy rozpoczyna od skopiowania ciągu danych foobar, ale ponieważ atakujący ustawił wartość 21, program memcpy kontynuuje działanie nawet po zakończeniu kopiowania 6 bajtów ciągu danych. Program memcpy dokonuje nadinterpretacji, najpierw do losowych danych przechowywanych obok ciągu danych, a następnie do klucza tajnego. W rezultacie klucz tajny trafia do bufora odpowiedzi, skąd ma zostać wysłany przez sieć. Bez analizy skażenia gra byłaby w tym momencie zakończona. Bufor odpowiedzi, w tym wyciekły klucz tajny, zostałby teraz odesłany do atakującego. Na szczęście w tym przykładzie użyto mechanizmu DTA, aby temu zapobiec. Po skopiowaniu klucza tajnego silnik DTA zauważa, że ​​kopiuje zanieczyszczone bajty i oznacza również bajty wyjściowe jako zanieczyszczone. Po zakończeniu działania funkcji memcpy i sprawdzeniu skażonych bajtów przed wykonaniem operacji wysyłania sieciowego, zauważysz, że część bufora odpowiedzi jest skażona, co pozwala wykryć atak Heartbleed. To tylko jedno z wielu zastosowań dynamicznej analizy skażeń, z których niektóre omówię w rozdziale 11. Jak wspomniałem, nie warto uruchamiać tego typu analizy DTA na serwerze produkcyjnym ze względu na znaczne spowolnienie, jakie ona powoduje. Jednak opisany przeze mnie rodzaj analizy dobrze sprawdza się w połączeniu z analizą rozmytą (ang. fuzzing), gdzie testuje się bezpieczeństwo aplikacji lub biblioteki, takiej jak OpenSSL, dostarczając jej pseudolosowo generowane dane wejściowe, takie jak żądania Heartbeat, w których pola ciągu i długości ładunku nie są zgodne. Aby wykryć błędy, analiza rozmyta opiera się na obserwowalnych zewnętrznie efektach, takich jak awaria lub zawieszenie się programu. Jednak nie wszystkie błędy powodują tak widoczne efekty, ponieważ błędy, takie jak wycieki informacji, mogą wystąpić po cichu, bez awarii lub zawieszenia się programu. Za pomocą DTA można rozszerzyć zakres obserwowanych błędów w rozmywaniu, uwzględniając błędy niepowodujące awarii, takie jak wycieki informacji. Ten rodzaj rozmycia mógł ujawnić obecność Heartbleed, zanim podatne wersje OpenSSL pojawiły się na rynku. Ten przykład dotyczył prostej propagacji skażenia, w której skażony klucz tajny był kopiowany bezpośrednio do bufora wyjściowego. Następnie omówię bardziej złożone typy propagacji skażenia z bardziej skomplikowanym przepływem danych.

Krótki przegląd luki Heartbleed

https://chacker.pl/

Heartbleed wykorzystuje klasyczny mechanizm nadczytania bufora w implementacji protokołu Heartbeat w OpenSSL (należy pamiętać, że Heartbeat to nazwa wykorzystywanego protokołu, a Heartbleed to nazwa exploita). Protokół Heartbeat umożliwia urządzeniom sprawdzenie, czy połączenie z serwerem obsługującym SSL jest nadal aktywne, poprzez wysłanie do serwera żądania Heartbeat zawierającego dowolny ciąg znaków określony przez nadawcę. Jeśli wszystko jest w porządku, serwer odpowiada, wysyłając ten ciąg w komunikacie odpowiedzi Heartbeat. Oprócz ciągu znaków, żądanie Heartbeat zawiera pole określające długość tego ciągu. To właśnie nieprawidłowe przetwarzanie tego pola długości skutkuje luką Heartbleed. Podatne na ataki wersje OpenSSL pozwalają atakującemu określić długość znacznie dłuższą niż rzeczywisty ciąg, co powoduje wyciek dodatkowych bajtów z pamięci serwera podczas kopiowania ciągu do odpowiedzi. Listing  przedstawia kod OpenSSL odpowiedzialny za błąd Heartbleed. Omówmy pokrótce, jak to działa, a następnie przeanalizujmy, jak DTA może wykrywać wycieki informacji związane z Heartbleed.

Listing : Kod powodujący lukę w zabezpieczeniach OpenSSL Heartbleed

Kod na Listingu  jest częścią funkcji OpenSSL, która przygotowuje odpowiedź Heartbeat po otrzymaniu żądania. Trzy najważniejsze zmienne na Listingu  to pl, payload i bp. Zmienna pl jest wskaźnikiem do ciągu danych w żądaniu Heartbeat, który zostanie skopiowany do odpowiedzi. Pomimo mylącej nazwy, payload nie jest wskaźnikiem do ciągu danych, ale liczbą typu unsigned int określającą długość tego ciągu. Zarówno pl, jak i payload są pobierane z komunikatu żądania Heartbeat, więc w kontekście Heartbleed są kontrolowane przez atakującego. Zmienna bp jest wskaźnikiem do bufora odpowiedzi, do którego kopiowany jest ciąg danych. Najpierw kod na Listingu 10-1 przydziela bufor odpowiedzi (1) i ustawia bp na początek tego bufora (2). Należy zauważyć, że rozmiar bufora jest kontrolowany przez atakującego za pomocą zmiennej payload. Pierwszy bajt w buforze odpowiedzi zawiera typ pakietu: TLS1_HB_RESPONSE (odpowiedź Heartbeat) (3). Kolejne 2 bajty zawierają długość ładunku, która jest po prostu kopiowana (przez makro s2n) ze zmiennej ładunku kontrolowanej przez atakującego (4). Teraz pojawia się sedno podatności Heartbleed: mechanizm kopiowania bajtów ładunku ze wskaźnika pl do bufora odpowiedzi (5). Przypomnijmy, że zarówno ładunek, jak i ciąg znaków przechowywany w pl są pod kontrolą atakującego. Zatem, podając krótki ciąg znaków i dużą liczbę jako ładunek, można oszukać mechanizm kopiowania, aby kontynuował kopiowanie poza ciąg żądania, ujawniając wszystko, co znajduje się w pamięci obok żądania. W ten sposób możliwe jest ujawnienie do 64 KB danych. Na koniec, po dodaniu losowych bajtów wypełnienia na końcu odpowiedzi (6), odpowiedź zawierająca ujawnione informacje jest wysyłana przez sieć do atakującego (7).

Wykorzystanie DTA do wykrywania luki Heartbleed

https://chacker.pl/

Aby zobaczyć, jak DTA może być przydatne w praktyce, zastanówmy się, jak można go użyć do wykrycia luki Heartbleed w OpenSSL. OpenSSL to biblioteka kryptograficzna, która jest szeroko stosowana do ochrony komunikacji w Internecie, w tym połączeń ze stronami internetowymi i serwerami pocztowymi. Luka Heartbleed może zostać wykorzystana do wycieku informacji z systemów korzystających z podatnej wersji OpenSSL. Może to obejmować bardzo poufne informacje, takie jak klucze prywatne oraz nazwy użytkowników i hasła przechowywane w pamięci.