2012-12-11 14 views
6

Muszę poprzedzić to pytanie stwierdzeniem, że jestem świadomy, że trudne kodowanie hasła w aplikacji klienckiej jest złą praktyką, z wielu powodów. Są inne pytania dotyczące tego problemu. Zakres tego pytania jest węższy i zakłada, że ​​uwierzytelnianie poświadczeń MUSI znajdować się w kodzie aplikacji klienckiej z pewnych powodów, na które nie masz wpływu.Jaki jest najbezpieczniejszy sposób osadzenia hasła w kodzie Java?

Jeśli niektóre sposoby są lepsze niż inne (na przykład: JPasswordField przechowuje hasło w tablicy znaków zamiast łańcucha) i jeśli musiałeś go zakodować w aplikacji Java, jakie środki mógłbyś podjąć, aby było trudniej być pobranym?

Aktualizacja:

Jedna instancja aplikacji działa na zdalnym komputerze, gdy użytkownik ma uprawnienia administratora. Poświadczenia są używane do uzyskania dostępu do bazy danych w tej samej sieci, więc faktyczne hasło jest już z góry określone i musi zostać wprowadzone ręcznie w rzeczywistym kodzie.

+1

Czy zastanawiałeś się nad hashowaniem hasła? Może to zadziała w twoim przypadku użycia? – Robin

+1

Czy możesz podać szczegóły dotyczące działania aplikacji klienckiej? Ile wystąpień tego działa? Kto kontroluje cykl życia? Do czego służy hasło? –

+1

Czy musisz wysłać hasło gdzie indziej, więc rzeczywiście potrzebujesz prawdziwego hasła? A może otrzymasz hasło skądś (takie jak użytkownik) i po prostu musisz sprawdzić, czy jest ono poprawne (i może użyć hasha)? – hyde

Odpowiedz

5

.... jeśli musiałeś mocno zakodować go w aplikacji Java , jakie środki mógłbyś podjąć, aby trudniej było je uzyskać?

Na początek chciałbym zrobić cholernie pewny, że osoba odpowiedzialna za zarządzanie za przeprowadzenie tej złej decyzji jest w pełni świadomy, że jest to całkowicie i nieodwracalnie niepewny .

Wtedy prawdopodobnie wymyśliłbym jakiś naff algorytmu, który montuje hasło w niejasny sposób; na przykładprzez zbudowanie dwóch tablic bajtowych i prześwietlanie ich razem ... i dystrybucję zaciemnionych bajtów. Najlepsze, co możesz zrobić, to utrudnić osobom o ograniczonych umiejętnościach odwrócenie kodu na hasło.

(Zaszyfrowanie hasła za pomocą silnego algorytmu niewiele pomoże, ponieważ wybór algorytmu i klucza deszyfrującego musi zostać osadzony w kodzie, w rzeczywistości każdy program, o którym można marzyć, można pokonać za pomocą debugger, aby ustawić punkt przerwania w punkcie, w którym hasło musi być jasne.)

1 ... a nawet Jon Skeet nie byłby w stanie go zabezpieczyć.


Jeśli niektóre sposoby są lepsze od innych (na przykład: JPasswordField przechowuje hasła w postaci tablicy char zamiast string) ...

Chcę tylko zauważyć, że normalne uzasadnienie używania tablicy znaków do przechowywania haseł w JPasswordField i tym podobne ma na celu ochronę przed złymi użytkownikami odczytującymi hasła z podstawowych zrzutów lub plików wymiany. W rzeczywistości nie pomoże to, ponieważ musimy założyć, że złego faceta ma wystarczającą kontrolę, aby dołączyć debugger do JVM i przechwycić bajty z tablicy char.

1

Jako ogólną wytyczną nigdy nie należy przechowywać hasła (oczywiście).

Jeśli potrzebujesz hasła dostępnego w środowisku wykonawczym, najlepszą praktyką (zalecane na przykład w książce Continuous Delivery autorstwa Jerzego Humble'a) jest podanie hasła przy uruchomieniu/uruchomieniu. W ten sposób hasło może znajdować się tylko w głowach ludzi, a nie gdzieś w niezabezpieczonym pliku.

Nie wiem, czy jest to możliwe w twoim przypadku, ale powinieneś dążyć do tego.

1

Domyślam się, że najmniej nieidealne rozwiązanie to, jeśli możesz mieć oparty na prowokacji protokół uwierzytelniania z losowym elementem w nim.

W ten sposób nie jest to tylko hasło, jest to również kod, który używa hasła do generowania poprawnych odpowiedzi, które należy poddać inżynierii wstecznej.

To może być również uwierzytelnianie dwukierunkowe, to znaczy, że twój koniec może zweryfikować, że druga strona również używa tego samego protokołu/algorytmu, a także ma to samo hasło.

Co najważniejsze, hasło nigdy nie jest wysyłane przez sieć, więc nie można go podsłuchać.

Diffie-Helman key exchange jest jednym z powszechnie używanych protokołów do takich rzeczy, ale zawsze można przetestować własną, prostą implementację, jeśli zależy nam tylko na zaciemnieniu, a nie na prawdziwych zabezpieczeniach. Cóż, prawdziwe bezpieczeństwo jest oczywiście poza twoim zasięgiem, jeśli wszystko może zostać zdekompilowane i przetworzone z kodu bajtowego, ale w każdym razie ... :)

1

Bardzo niebezpieczne jest przechowywanie poufnych danych po stronie klienta, zwłaszcza po hasło, ponieważ pliki .class można łatwo dekompilować. Czy zastanawiasz się kiedyś nad asymetrycznym szyfrowaniem? Jak para kluczy publicznych/prywatnych lub coś w tym stylu?

0

Lubię odpowiedź Stefana, ale chciałbym dodać ...

bezpieczeństwo kodu źródłowego jest zbyt ważne. Bez względu na to, jaką metodę używasz do zaciemniania hasła, każdy, kto ma dostęp do źródła, może łatwo umieścić kod System.out.println(password) i przechwycić hasło w miejscu, w którym jest używany, lub uruchomić kod podczas debugowania i zatrzymać kod w celu sprawdzenia zmiennych.

Nawet bez kompilacji, każdy, kto ma dostęp do jar, może uruchomić program java w trybie debugowania i zatrzymać program, w którym używane jest hasło, i sprawdzić zmienną, banalnie z kodem źródłowym, ale nadal można to zrobić przy użyciu tylko słoika i niektóre narzędzia.

Możesz rozważyć możliwość uzyskania przez program hasła z bezpiecznego serwera, gdy jest on potrzebny (za pośrednictwem usługi sieciowej lub innego podobnego narzędzia) i niech ten serwer używa zapory sieciowej, aby zezwolić na dostęp do niej tylko określonym adresom IP (jeśli adres IP maszyny klienta są znane). Nadal nie jest bezpieczny, ale przynajmniej to jest coś.

Powiązane problemy