.class
Pliki Java można dość łatwo dekompilować. Jak mogę chronić swoją bazę danych, jeśli muszę używać danych logowania w kodzie?
java
mysql
security
reverse-engineering
decompiling
Jakob Cosoroaba
źródło
źródło
Odpowiedzi:
Nigdy nie wpisuj haseł na stałe do swojego kodu. Niedawno pojawiło się to na liście 25 najbardziej niebezpiecznych błędów w programowaniu :
Informacje konfiguracyjne, w tym hasła, należy przechowywać w oddzielnym pliku, który aplikacja odczytuje podczas uruchamiania. To jedyny prawdziwy sposób, aby zapobiec wyciekowi hasła w wyniku dekompilacji (nigdy nie kompiluj go do pliku binarnego na początek).
Więcej informacji na temat tego częstego błędu można znaleźć w artykule CWE-259 . Artykuł zawiera dokładniejszą definicję, przykłady i wiele innych informacji na temat problemu.
W Javie jednym z najłatwiejszych sposobów jest użycie klasy Preferences. Jest przeznaczony do przechowywania wszelkiego rodzaju ustawień programu, z których niektóre mogą zawierać nazwę użytkownika i hasło.
import java.util.prefs.Preferences; public class DemoApplication { Preferences preferences = Preferences.userNodeForPackage(DemoApplication.class); public void setCredentials(String username, String password) { preferences.put("db_username", username); preferences.put("db_password", password); } public String getUsername() { return preferences.get("db_username", null); } public String getPassword() { return preferences.get("db_password", null); } // your code here }
W powyższym kodzie możesz wywołać
setCredentials
metodę po wyświetleniu okna dialogowego z pytaniem o nazwę użytkownika i hasło. Gdy potrzebujesz połączyć się z bazą danych, możesz po prostu użyć metodgetUsername
igetPassword
, aby pobrać zapisane wartości. Dane logowania nie zostaną zakodowane na stałe w Twoich plikach binarnych, więc dekompilacja nie będzie stanowić zagrożenia dla bezpieczeństwa.Ważna uwaga: Pliki preferencji to zwykłe pliki tekstowe XML. Upewnij się, że podejmujesz odpowiednie kroki, aby uniemożliwić nieautoryzowanym użytkownikom przeglądanie plików surowych (uprawnienia UNIX, uprawnienia systemu Windows itp.). Przynajmniej w Linuksie nie stanowi to problemu, ponieważ wywołanie
Preferences.userNodeForPackage
spowoduje utworzenie pliku XML w katalogu domowym bieżącego użytkownika, który i tak jest nieczytelny dla innych użytkowników. W systemie Windows sytuacja może wyglądać inaczej.Więcej ważnych uwag: W komentarzach do tej odpowiedzi i innych było wiele dyskusji na temat prawidłowej architektury w tej sytuacji. Oryginalne pytanie tak naprawdę nie wspomina o kontekście, w którym aplikacja jest używana, więc opowiem o dwóch sytuacjach, które przychodzą mi do głowy. Pierwszy to przypadek, w którym osoba korzystająca z programu już zna (i ma prawo znać) dane uwierzytelniające do bazy danych. Drugi to przypadek, w którym programista próbuje ukryć dane uwierzytelniające bazy danych przed osobą korzystającą z programu.
Pierwszy przypadek: użytkownik jest upoważniony do poznania danych logowania do bazy danych
W takim przypadku sprawdzi się rozwiązanie, o którym wspomniałem powyżej.
Preference
Klasa Java będzie przechowywać nazwę użytkownika i hasło w postaci zwykłego tekstu, ale plik preferencji będzie mógł odczytać tylko upoważniony użytkownik. Użytkownik może po prostu otworzyć plik XML preferencji i odczytać dane logowania, ale nie stanowi to zagrożenia dla bezpieczeństwa, ponieważ na początku znał dane uwierzytelniające.Drugi przypadek: próba ukrycia danych logowania przed użytkownikiem
Jest to bardziej skomplikowany przypadek: użytkownik nie powinien znać danych logowania, ale nadal potrzebuje dostępu do bazy danych. W takim przypadku użytkownik uruchamiający aplikację ma bezpośredni dostęp do bazy danych, co oznacza, że program musi wcześniej znać dane logowania. Rozwiązanie, o którym wspomniałem powyżej, nie jest odpowiednie w tym przypadku. Możesz przechowywać dane logowania do bazy danych w pliku preferencji, ale użytkownik będzie mógł odczytać ten plik, ponieważ będzie właścicielem. W rzeczywistości nie ma dobrego sposobu na bezpieczne korzystanie z tego przypadku.
Prawidłowy przypadek: użycie architektury wielowarstwowej
Prawidłowym sposobem na to jest utworzenie warstwy pośredniej między serwerem bazy danych a aplikacją kliencką, która uwierzytelnia poszczególnych użytkowników i umożliwia wykonanie ograniczonego zestawu operacji. Każdy użytkownik miałby własne poświadczenia logowania, ale nie do serwera bazy danych. Poświadczenia umożliwiałyby dostęp do warstwy środkowej (warstwy logiki biznesowej) i byłyby różne dla każdego użytkownika.
Każdy użytkownik miałby własną nazwę użytkownika i hasło, które można przechowywać lokalnie w pliku preferencji bez żadnego zagrożenia bezpieczeństwa. Nazywa się to architekturą trójwarstwową (warstwy to serwer bazy danych, serwer logiki biznesowej i aplikacja kliencka). Jest to bardziej złożone, ale naprawdę jest to najbezpieczniejszy sposób zrobienia tego rodzaju rzeczy.
Podstawowa kolejność operacji to:
getInventoryList
.Zauważ, że w całym procesie aplikacja kliencka nigdy nie łączy się bezpośrednio z bazą danych . Warstwa logiki biznesowej otrzymuje żądanie od uwierzytelnionego użytkownika, przetwarza żądanie klienta dotyczące listy zapasów, a dopiero potem wykonuje zapytanie SQL.
źródło
Umieść hasło w pliku, który odczyta aplikacja. NIGDY nie osadzaj haseł w pliku źródłowym. Kropka.
Ruby ma mało znany moduł o nazwie DBI :: DBRC do takiego użycia. Nie wątpię, że Java ma odpowiednik. Zresztą napisanie takiego nie jest trudne.
źródło
Piszesz aplikację internetową? Jeśli tak, użyj JNDI, aby skonfigurować go zewnętrznie w aplikacji. Przegląd jest dostępny tutaj :
źródło
Bez względu na to, co zrobisz, poufne informacje będą przechowywane gdzieś w jakimś pliku. Twoim celem jest uczynienie go tak trudnym, jak to tylko możliwe. To, ile z tego możesz osiągnąć, zależy od Twojego projektu, potrzeb i grubości portfela Twojej firmy.
Najlepszym sposobem jest nigdzie nie przechowywanie haseł. Osiąga się to za pomocą funkcji skrótu do generowania i przechowywania skrótów haseł:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
Niepowiązana uwaga: W dawnych czasach internetu po kliknięciu łącza „Nie pamiętam hasła” strony internetowe wysyłały pocztą e-mail hasło w postaci zwykłego tekstu. Prawdopodobnie przechowywali je gdzieś w bazie danych. Gdy hakerzy uzyskaliby dostęp do ich bazy danych, uzyskaliby dostęp do wszystkich haseł. Ponieważ wielu użytkowników używałoby tego samego hasła w wielu witrynach internetowych, był to ogromny problem z bezpieczeństwem. Na szczęście w dzisiejszych czasach nie jest to powszechna praktyka.
Teraz pojawia się pytanie: jaki jest najlepszy sposób przechowywania haseł? Uznałbym tego (uwierzytelnianie i zarządzanie użytkownikami usług stormpath za) rozwiązanie dość jedna cholernie idealny:
Oczywiście nie jesteś Google ani bankiem, więc jest to dla Ciebie przesada. Ale potem pojawia się pytanie: ile bezpieczeństwa wymaga Twój projekt, ile masz czasu i pieniędzy?
W przypadku wielu aplikacji, chociaż nie jest to zalecane, przechowywanie zakodowanego na stałe hasła w kodzie może być wystarczająco dobrym rozwiązaniem. Jednak dzięki łatwemu dodaniu kilku dodatkowych kroków zabezpieczeń z powyższej listy możesz uczynić swoją aplikację znacznie bezpieczniejszą.
Na przykład załóżmy, że krok 1 nie jest akceptowalnym rozwiązaniem dla twojego projektu. Nie chcesz, aby użytkownicy wpisywali hasło za każdym razem lub nawet nie chcesz, aby użytkownicy znali hasło. Nadal masz gdzieś poufne informacje i chcesz je chronić. Masz prostą aplikację, nie ma serwera do przechowywania plików lub jest to zbyt kłopotliwe dla Twojego projektu. Twoja aplikacja działa w środowiskach, w których nie jest możliwe bezpieczne przechowywanie plików. To jeden z najgorszych przypadków, ale mimo to dzięki dodatkowym środkom bezpieczeństwa możesz mieć znacznie bezpieczniejsze rozwiązanie. Na przykład możesz przechowywać poufne informacje w pliku i możesz zaszyfrować plik. Możesz mieć prywatny klucz szyfrowania zakodowany na stałe w kodzie. Możesz zaciemnić kod, więc utrudniasz komuś złamanie go.ten link . (Chcę jeszcze raz Cię ostrzec, że nie jest to w 100% bezpieczne. Sprytny haker z odpowiednią wiedzą i narzędziami może to zhakować. Jednak w oparciu o Twoje wymagania i potrzeby może to być wystarczająco dobre rozwiązanie dla Ciebie).
źródło
To pytanie pokazuje, jak przechowywać hasła i inne dane w zaszyfrowanym pliku: 256-bitowe szyfrowanie Java AES oparte na hasłach
źródło
MD5 to algorytm mieszający, a nie algorytm szyfrowania, w skrócie nie można odzyskać haszowania, można tylko porównać. Powinien być idealnie używany do przechowywania informacji uwierzytelniających użytkownika, a nie nazwy użytkownika i hasła db. nazwa użytkownika db i pwd powinny być zaszyfrowane i przechowywane w pliku konfiguracyjnym, co najmniej.
źródło