Signal przez ostatnie kilka lat zapracował sobie na opinię bezpiecznego komunikatora, który stawia na prywatność użytkowników. Signal wykorzystywany jest zarówno przez indywidualnych użytkowników, którzy cenią sobie prywatność, ale także jako domyślny komunikator w firmach i instytucjach. Dzięki niedawnej aferze Signal-gate wiemy również, iż komunikator ten jest wykorzystywany w kręgach administracji rządowej USA.

Jak wypada Signal na tle konkurencji?
Zanim przejdziemy do meritum, należy podkreślić, iż Signal jest aplikacją, która faktycznie zapewnia poufność przesyłanych danych. Wykorzystuje on szyfrowane end-to-end (E2EE – End-To-End Encryption). Oznacza to, iż wiadomość jest szyfrowana na urządzeniu nadawcy i odszyfrowywana dopiero na urządzeniu odbiorcy. Dzięki temu choćby twórcy aplikacji nie mają dostępu do treści rozmów użytkowników. Signal do szyfrowania wykorzystuje swój autorski, open-source protokół „Signal Protocol”- https://github.com/signalapp/libsignal.

O ile sama aplikacja Signal jest bezpieczna i sprawdzona, o tyle twórcy narzędzia nie są w stanie zabezpieczyć użytkowników przed:
- Ataki socjotechnicznymi
- Przejęciem kontroli nad urządzeniem na poziomie systemu operacyjnego
W dalszej części wpisu postaramy się zasymulować działania atakującego, który uzyskał dostęp do komputera ofiary i chce odczytać wiadomości.
Jak działa Signal Desktop?
Signal Desktop to aplikacja Desktopowa na urządzenia Windows, MacOS i Linux, która umożliwia dostęp do Signala z poziomu Desktopu. Możemy dodać dowolną ilość takich urządzeń do swojego konta korzystając z aplikacji na telefonie i opcji „Linked Device”.
W systemie Windows Signal Desktop przechowuje najważniejsze informacje w trzech plikach:
- Local State – który zawiera zaszyfrowany przez DPAPI klucz służący do szyfrowania docelowego klucza szyfrującego wiadomości
- config.json – który zawiera zaszyfrowany klucz służący do szyfrowania wiadomości
- db.sqlite – baza danych sqlite, z rozszerzeniem „cipher”, która umożliwia szyfrowanie zawartości. To właśnie w tej bazie znajdują się nasze rozmowy dostępne w aplikacji Signal Desktop. Baza ta jest szyfrowana kluczem znajdującym się w pliku „config.json”.

Dygresja – czyli jak to wcześniej z Signal Desktop bywało?
Do połowy ubiegłego roku, Signal przechowywał klucz szyfrujący bazę danych w formie plaintext. Po niemałej burzy, która rozpętała się w świecie cybersecurity programiści zabezpieczyli klucz z config.json dzięki DPAPI. Więcej o tej sytuacji możecie przeczytać tutaj.
W jaki sposób odczytać wiadomości Signal Desktop?
Ponieważ mamy tutaj do czynienia z DPAPI i dość podobnym mechanizmem do zastosowanego w Chromium, możemy spróbować zastosować technikę z wcześniejszych wpisów.

Odzyskanie zaszyfrowanego klucza z Local State i odszyfrowanie go (Krok 1 oraz 2)
W celu odzyskania klucza z Local State wystarczy użyć następującej funkcji:

Powyższa funkcja najpierw parsuje plik „Local State”, a następnie odzyskuje z niego wartość „encrypted_key”. Z tego ciągu bajtów usuwamy pierwsze 5 bajtów, które odpowiadają za tekst („DPAPI”), a następnie całość deszyfrujemy dzięki wbudowanej funkcji ProtectedData.Unprotect.
Deszyfrowanie docelowego klucza z pliku config.json (Krok 3)

Powyższa funkcja po raz kolejny parsuje plik JSON, tym razem w celu wydobycia zawartości pola „encryptedKey”. Następnie deszyfruje go dzięki algorytmu AES w trybie GCM, wyświetla na ekran oraz zwraca do innych funkcji w formie bajtów.

Odczytanie wiadomości z bazy SQLite
W celu odczytania zawartości zaszyfrowanej bazy SQLite skorzystałem z narzędzia DB Browser for SQLCipher.
Po próbie załadowania bazy, program prawidłowo odczytał, iż jest ona zaszyfrowana i poprosił o dane umożliwiające jej odszyfrowanie.

Tutaj miała miejsce krótka zabawa, ponieważ nie miałem pojęcia jakie parametry szyfrowania zostały zastosowane. Nie wiedziałem również w jakiej formie mam podać klucz do odszyfrowania bazy danych:
- passphrase
- Raw key
W anglojęzycznych opracowaniach znalazłem informacje, iż np. stosowane algorytmy HMAC oraz KDF to SHA1. Metodą prób i błędów udało mi się jednak ustalić, iż Signal Desktop korzysta z zaszyfrowanej bazy danych korzystającej z domyślnych ustawień SQLCipher 4, a do szyfrowania używa klucza w formie ciągu bajtów czyli „raw key”.
Odczytane wiadomości

Jak widać, klucz odzyskany przez mój program okazał się być prawidłowy. Baza danych została odszyfrowana, a ja widzę wszystkie wiadomości zapisane jawnym tekstem.
Czy to podatność?
Oczywiście, iż nie. To feature. Signal zabezpieczył plik z kluczem (config.json) dzięki wbudowanego mechanizmu bezpieczeństwa systemu Windows (DPAPI). o ile ma być tutaj zachowany odpowiedni poziom User Experiance, aplikacja powinna deszyfrować wiadomości w locie, bez konieczności podawania dodatkowego hasła przy załadowaniu (jak np. w KeePass). Dzięki temu dane w spoczynku są zaszyfrowane, a użytkownik dostaje je odszyfrowane podczas korzystania z narzędzia.
Alternatywa?
Moim zdaniem aplikacja Signal na urządzeniach mobilnych jest bezpieczniejsza niż na Desktopie. Zanim posypią się na mnie gromy – pozwólcie, iż przedstawię jeden argument: przejęcie kontroli nad telefonem użytkownika jest trudniejsze niż nad stacją roboczą. Systemy iOS oraz Android posiadają więcej warstw ochronnych i są lepiej zoptymalizowanymi systemami pod kątem bezpieczeństwa. Malware i RATy na ww. urządzenia również są mniej dojrzałe i gorzej dostępne od tych na systemy Windows.
Czy Signal powinien szyfrować klucz z config.json passphrase lub np. kluczem sprzętowym zamiast korzystać z DPAPI?
Pytanie to jest bardzo szerokie i tak naprawdę sprowadza się do ustalenia odpowiedzialności za system użytkownika. o ile twórcy Signala zakładają, iż ochrona systemu operacyjnego powinna być realizowana niezależnie (i słusznie), to korzystanie z DPAPI jest dobrym wyborem. Jednak w przypadku kompromitacji stacji, odzyskanie wiadomości staje się dość proste.
Jakie mamy alternatywy?
- Passphrase
- Szyfrowanie z wykorzystaniem klucza sprzętowego
- Szyfrowanie z wykorzystaniem biometrii
Każde z tych rozwiązań wiąże się z kompromisem między bezpieczeństwem a wygodą użytkowania. Zaryzykowałbym jednak stwierdzenie, iż twórcy aplikacji Signal Desktop powinni udostępnić dodatkową formę zabezpieczenia bazy danych jako feature – wybór należałby wtedy do użytkownika.
Todo
W kolejnym wpisie postaram się przeanalizować tabele i kolumny bazy db.sqlite i spróbować napisać ekstraktor wiadomości, który będzie przesyłał korespondencję użytkownika dzięki bezpiecznego kanału komunikacji do C2 adwersarza. Stay tuned