CVE-2025-5922: Możliwy do odzyskania skrót hasła chroniącego konsolę administracyjną TSplus

Podczas testów penetracyjnych przeprowadzonych w jednej z firm wykryłem podatność w oprogramowaniu TSplus Remote Access. Aplikacja przechowywała skrót kodu PIN administratora w rejestrze systemu Windows w formacie SHA-256, bez zastosowania mechanizmów takich jak sól czy pieprz. Lokalizacja tego wpisu była łatwa do zidentyfikowania dzięki analizie nieobfuskowanej biblioteki .NET, wykorzystywanej przez aplikację. Uzyskany skrót PIN-u, zapisany w rejestrze, okazał się możliwy do odnalezienia w publicznej bazie skrótów, co pozwoliło na natychmiastowe uzyskanie właściwej wartości – bez potrzeby jego łamania. W rezultacie uzyskałem dostęp do panelu administratora, a także możliwość podglądu oraz przejmowania sesji innych użytkowników w obrębie tego samego hosta.

CVE-2025-5922: Możliwy do odzyskania skrót hasła chroniącego konsolę administracyjną TSplus

Ogólny zarys

TSplus Remote Access to popularne rozwiązanie do zdalnego dostępu i udostępniania aplikacji, wykorzystywane przez firmy na całym świecie. Podczas jednego z komercyjnych testów bezpieczeństwa, realizowanego dla klienta wspólnie z zespołem DSecure.me, wykryłem problem związany z przechowywaniem danych uwierzytelniających administratora. Okazało się, że aplikacja zapisuje skrót hasła administratora (a dokładniej kodu PIN) w rejestrze systemowym w sposób całkowicie podatny na atak offline. Skrót ten nie był w żaden sposób zabezpieczony – brakowało soli, pieprzu, a także jakiejkolwiek formy szyfrowania lub ukrycia lokalizacji. Aplikacja co prawda umożliwia rozdzielenie ról i ograniczanie dostępu, jednak naszym celem było uzyskanie dostępu do konta administratora poprzez zdalne połączenie z atakowaną maszyną. Prace rozpoczęliśmy od przejęcia kontroli nad interfejsem powłoki systemowej (CMD/Powershell), ponieważ nawet te funkcje były zablokowane dla zwykłego użytkownika. Po uzyskaniu dostępu do PowerShella możliwe stało się również przeglądanie zawartości dysku C: – wcześniej zablokowane dla konta użytkownika. Następnym celem była aplikacja TSplus Remote Access, odpowiadająca za zdalne logowanie do serwera. Po kilku godzinach analizy i inżynierii wstecznej różnych komponentów aplikacji udało się zidentyfikować wspólną bibliotekę, odpowiedzialną za proces uwierzytelniania do panelu administratora oraz sposób i lokalizację, w której przechowywany jest kod PIN. Choć dostęp do poświadczeń administratora uzyskaliśmy w inny sposób, samodzielne uzyskanie dostępu do panelu pozwoliło na aktywację możliwości logowania dla konta administratora. W ten sposób osiągnęliśmy zakładany cel ataku.

Na czym polega podatność?

Aby możliwe było wykorzystanie opisanej w niniejszym artykule podatności związanej ze słabym mechanizmem przechowywania kodu PIN i uzyskanie dostępu do panelu AdminTool.exe, musi zostać spełniony jeden warunek. Administrator systemu w narzędziu AdminTool.exe musi zaznaczyć opcję “Disable UAC and enhance Windows access” (Rys. 1). Funkcja ta wyłącza kontrolę UAC podczas uruchamiania narzędzia, przez co ochrona dostępu do AdminTool.exe ogranicza się wyłącznie do wspomnianego kodu PIN. Z jakiego powodu administrator mógłby aktywować tę opcję - nie wiem. Faktem jest jednak, że w środowisku, w którym wykryto opisaną podatność, opcja ta była aktywna.

Rys 1. Opcja zaznaczona przez administratora systemu, wymagana do wystąpienia podatności.
Rys 1. Opcja zaznaczona przez administratora systemu, wymagana do wystąpienia podatności.

Kontynuując, aplikacja przechowuje skrót kodu PIN administratora w formacie SHA-256 w rejestrze systemowym, bez zastosowania jakichkolwiek dodatkowych mechanizmów bezpieczeństwa (takich jak sól czy pieprz). Pomimo ograniczonych uprawnień, użytkownik systemu z najniższym poziomem dostępu ma możliwość odczytania tej wartości, co umożliwia przeprowadzenie ataku offline brute-force lub wykorzystanie rainbow tables. Dodatkowo:

  • Aplikacja nie wymusza stosowania zasad tworzenia silnych haseł (np. minimalnej długości, złożoności znaków).
  • Wpis w rejestrze jest przechowywany w sposób łatwy do odnalezienia – jego lokalizacja może zostać szybko ustalona za pomocą inżynierii wstecznej nieobfuskowanej biblioteki Api.dll, napisanej w .NET, lub – przy wyższych uprawnieniach – poprzez monitorowanie procesów systemowych.
  • Warto także zauważyć, że interfejs logowania określa hasło jako „PIN”, co może skłaniać użytkowników do stosowania krótkich, numerycznych i słabych wartości zamiast silnych haseł alfanumerycznych.

Ważne: uprawnienia w aplikacji są ograniczane przez uprawnienia użytkownika w systemie operacyjnym. Na przykład, jeśli użytkownik nie ma uprawnień do zapisu pliku konfiguracyjnego. Ma jednak możliwość podglądu sesji innych użytkowników oraz ich przechwytywania.

PoC

Poniżej przedstawiam sposób wykrycia podatności oraz przykład kodu C#, umożliwiającego pobranie wszystkich kluczy rejestru dla oprogramowania TSplus Remote Access w wersji 17.2025.5.13.

Pierwsze uruchomienie aplikacji AdminTool.exe skutkuje wyświetleniem monitu o podanie kodu PIN administratora (Rys. 2). W przypadku wprowadzenia nieprawidłowego PIN-u aplikacja zwraca komunikat błędu, jak pokazano na Rys. 3.

Rys 2. Uruchomienie programu AdminTool.exe skutkuje wyświetleniem monitu z prośbą o podanie kodu PIN.
Rys 2. Uruchomienie programu AdminTool.exe skutkuje wyświetleniem monitu z prośbą o podanie kodu PIN.
Rys 3. W przypadku wprowadzenia nieprawidłowego kodu PIN użytkownik otrzymuje odpowiedni komunikat.
Rys 3. W przypadku wprowadzenia nieprawidłowego kodu PIN użytkownik otrzymuje odpowiedni komunikat.

Sama aplikacja AdminTool.exe została napisana w .NET i poddana silnej obfuskacji, co znacznie utrudnia jej analizę. Wśród zależności wykorzystywanych przez aplikację zauważyłem dodatkową bibliotekę Api.dll. Do jej analizy skłonił mnie fakt, że całe oprogramowanie TSplus Remote Access składa się z kilku komponentów – każdy z nich żąda tego samego kodu PIN. Sugerowało to, że mechanizm logowania administratora został wyodrębniony do wspólnej biblioteki. Jak się okazało – słusznie (Rys. 4).

Rys 4. Wykryta zależność od biblioteki Api.dll, znajdującej się w pliku AdminTool.exe.
Rys 4. Wykryta zależność od biblioteki Api.dll, znajdującej się w pliku AdminTool.exe.

Podczas analizy Api.dll zauważyłem, że kod tej biblioteki nie został poddany obfuskacji, co znacznie ułatwiło jego analizę oraz wyszukiwanie fragmentów odpowiadających za wrażliwe operacje. Na Rys. 5 przedstawiono odnaleziony klucz rejestru, w którym przechowywana jest wartość PIN ustawiona przez administratora systemu. Z kolei Rys. 6 pokazuje sposób obliczania skrótu dla tej wartości.

Rys 5. Lokalizacja kodu PIN w rejestrze systemowym.
Rys 5. Lokalizacja kodu PIN w rejestrze systemowym.
Rys 6. Metoda używana do obliczenia skrótu.
Rys 6. Metoda używana do obliczenia skrótu.

W dalszej części poprosiłem ChatGPT o wygenerowanie kodu C#, który pobierze wszystkie wartości z rejestru dla zadanego drzewa. Wygenerowany kod zapisałem w notatniku. Na atakowanej maszynie, wykorzystując technikę Living off the Land (LotL), skompilowałem program przy użyciu kompilatora csc.exe z lokalizacji:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe poc.cs
using System;
using Microsoft.Win32;

class Program
{
    static void Main()
    {
        try
        {
            string regPath = @"SOFTWARE\Digital River";
            TraverseRegistry(Registry.LocalMachine, regPath);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error reading registry: " + ex.Message);
        }
    }

    static void TraverseRegistry(RegistryKey root, string path)
    {
        using (RegistryKey key = root.OpenSubKey(path))
        {
            if (key == null)
            {
                Console.WriteLine("Registry key not found: " + path);
                return;
            }

            Console.WriteLine("Key: " + path);

            foreach (string valueName in key.GetValueNames())
            {
                object value = key.GetValue(valueName);
                Console.WriteLine("  " + valueName + " = " + (value != null ? value.ToString() : "(null)"));
            }

            foreach (string subKeyName in key.GetSubKeyNames())
            {
                string subPath = path + "\\" + subKeyName;
                TraverseRegistry(root, subPath);
            }
        }
    }
}

Po uruchomieniu skompilowanego pliku uzyskałem skrót PIN-u administratora (Rys. 7). Ponieważ skrót nie był zabezpieczony ani solą, ani pieprzem, postanowiłem w pierwszej kolejności sprawdzić jego obecność w publicznych bazach skrótów. Jak się okazało – odnalezienie wartości oryginalnej zajęło kilka sekund (Rys. 8).

Rys 7. Skrót uzyskany z rejestru.
Rys 7. Skrót uzyskany z rejestru.
Rys 8. Odnalezienie skrótu.
Rys 8. Odnalezienie skrótu.

Po wprowadzeniu odnalezionej wartości uzyskałem dostęp do panelu administratora aplikacji TSplus Remote Access (Rys. 9).

Rys 9. Logowanie do aplikacji przy użyciu pozyskanego kodu PIN.
Rys 9. Logowanie do aplikacji przy użyciu pozyskanego kodu PIN.

Podsumowanie

Całość podatności można opisać w następujący sposób: Jeżeli administrator z jakiegokolwiek powodu aktywuje opcję „Disable UAC and enhance Windows access”, ograniczając w ten sposób zabezpieczenia aplikacji wyłącznie do mechanizmu kodu PIN (bo tylko taka ochrona wówczas pozostaje), to sam sposób przechowywania i weryfikacji tego PIN-u jest podatny na złamanie. W konsekwencji możliwe staje się nieautoryzowane uzyskanie dostępu do AdminTool.exe.

Oś czasu

DataAkcja
21 maj 2025Raport wysłany do CERT Polska
24 lipca 2025Naprawienie podatności w TSPlus
29 lipca 2025Publikacja CVE

Jak zapobiegać podobnym podatnością w swojej aplikacji

Aby uniknąć podobnych błędów projektowych i implementacyjnych, warto zastanowić się wdrożeniem następujących dobrych praktyk:

  • Nie przechowuj skrótów haseł w rejestrze systemowym. Wrażliwe dane uwierzytelniające powinny być przechowywane w dedykowanych, bezpiecznych mechanizmach (np. Windows Credential Manager, DPAPI, sejf aplikacyjny).
  • Stosuj unikalną sól dla każdego użytkownika. Skrót hasła lub PIN-u powinien być zawsze generowany z użyciem losowej wartości (salt), aby uniemożliwić użycie rainbow tables oraz identyfikację użytkowników po identycznych hasłach.
  • Dodaj pieprz po stronie aplikacji. Stała, trzymana poza bazą (np. w konfiguracji serwera), dodatkowa wartość używana do skracania haseł skutecznie utrudnia ataki offline.
  • Używaj funkcji haszujących odpornych na brute-force. Algorytmy takie jak bcrypt, scrypt czy Argon2 są znacznie bezpieczniejsze niż klasyczne funkcje typu SHA-256.
  • Wymuszaj zasady tworzenia silnych haseł. Użytkownicy powinni być zmuszani do stosowania wartości o odpowiedniej długości, złożoności oraz unikalności.
  • Unikaj mylącego nazewnictwa. Określenie hasła jako „PIN” może sugerować, że dopuszczalne są krótkie, numeryczne wartości. Nazewnictwo w interfejsie powinno odzwierciedlać wagę zabezpieczanej funkcji.
  • Obfuskacja kodu odpowiedzialnego za uwierzytelnienie. Krytyczne biblioteki, szczególnie w aplikacjach .NET, powinny być obfuskowane, aby utrudnić reverse engineering.
  • Ogranicz dostęp do kluczy rejestru. Jeżeli rejestr musi być użyty, dostęp do wpisów powinien być możliwy wyłącznie dla kont z odpowiednimi uprawnieniami (np. SYSTEM).
  • Unikaj współdzielenia mechanizmów logowania pomiędzy komponentami bez kontroli kontekstu. Jeżeli różne aplikacje korzystają z tego samego PIN-u, kompromitacja jednej z nich oznacza kompromitację całej platformy.

Bibliografia

  1. https://tsplus.eu/
  2. https://cert.pl/en/posts/2025/07/CVE-2025-5922