Szyfrowanie haseł i przetrzymywanie w bazie danych

Problem:

Tworzę konto na zewnętrzym serwisie poprzez ich API, gdzie muszę podać jakieś hasło. Nie jest dla mnie to na dobrą sprawę ważne jakie to będzie hasło. Później to hasło muszę gdzieś w bazie zapisać, żeby potem móc się dostać do danych na tym założonym koncie z poziomu mojej aplikacji.

Moje rozwiązanie:

Hasło generuję randomowo SecureRandom.hex(8) i potem używając https://github.com/Gurpartap/aescrypt je szyfruję: AESCrypt.encrypt(random_password, Rails.application.secrets[:secret_password] - gdzie drugi argument trzymany jest w pliku secrets.yml - jakiś długi klucz używany do szyfrowania. Potem sprawa jest już prosta, by dostać się do tego konta muszę hasło odszyfrować: AESCrypt.decrypt(@project.wallet.password, Rails.application.secrets[:secret_password])

W ten sposób mam dynamicznie generowane hasła, które jest zaszyfrowane w bazie, możemy je odczytać i połączyć się z wcześniej utworzonym kontem tylko przy odszyfrowaniu go.

Moje pytanie: Czy to dobre rozwiązanie? :slight_smile: Czy jest jakieś lepsze / bardziej bezpieczne? Czy AESCrypt może mieć jakieś luki? Macie jakieś podobne doświadczenia z tematem?

1 Like

A jest sens w ogóle to hasło szyfrować?

I tak każdy, kto ma dostęp do serwera ma też dostęp do pliku secrets.yml, więc je sobie odszyfruje bez problemu. Bazę danych masz pewnie na tej samej maszynie, więc ktoś kto uzyska dostęp do jednego, ma też dostęp do drugiego :wink:

Dobra praktyka. Po prostu. Haseł nie przechowuje się inaczej niż przynajmniej jako hash(password+salt).

Dobra praktyka zakłada, że haseł nie da się odzyskać (czyli proces jest jednostronny). Tutaj proces jest jak najbardziej odwracalny i wszystkie potrzebne do tego dane są na samym serwerze.

Zrozumiałbym jeśli np. byłby to task rake’owy i admin uruchamiając tego taska musiał podać hasło do odszyfrowania danych dostępowych z bazy. A w takiej sytuacji to sztuka dla sztuki i fałszywe poczucie bezpieczeństwa.

Różnica polega na tym, że jak ktoś dobierze się tylko do bazy to bez szyfrowania otrzyma hasełko w czystej postaci. A z solą i szyfrowaniem nic z tym hashem nie zrobi. Twoje rozumowanie jest na zasadzie, po co mam zamykać drzwi na klucz skoro złodziej może wybić szybę w oknie.

Czy my na pewno czytamy tego samego posta? Bo mam wątpliwości.

A z solą i szyfrowaniem nic z tym hashem nie zrobi.

Sól w tym wypadku nie ma nic do rzeczy. W bazie nie ma hasha, tylko szyfrogram - to duża różnica.
I oczywiście, że zrobi - wystarczy, że dobierze się do hasła, które też jest na serwerze.

Twoje rozumowanie jest na zasadzie, po co mam zamykać drzwi na klucz skoro złodziej może wybić szybę w oknie.

Raczej - “nie ma żadnej różnicy między zostawianiem roweru nieprzypiętego, a przypiętego na linkę z zostawionym kluczem w zamku”.

Mam wrażenie, że z sobie tylko znanych powodów zakładasz, że jak ktoś się włamie na serwer to od razu będzie miał dostęp do root’a, czy ogólnie pełny dostęp do wszystkich zasobów na tym serwerze. Nie wiem dlaczego nie bierzesz pod uwagę tego, że ktoś może się dostać np. tylko do dumpa bazy.

Co z tego że szyfrogram a nie hash. X znaków hasła + Y znaków soli. Nie znasz długości ani hasła ani soli. Powiedz mi ile czasu więcej zajmie Ci znalezienie co rzeczywiście jest hasłem w stosunku do hasła zapisanego w czystej postaci?

Nie po to się szyfruje dane, żeby nikt nigdy nie złamał szyfru, bo takich szyfrów nie ma, i nie będzie. Tylko po to, żeby złamanie szyfrów zajęło tyle zasobów i czasu, żeby to łamanie było nie opłacalne, żeby koszt łamania przewyższał zysk ze złamania.

1 Like

Mam wrażenie, że z sobie tylko znanych powodów zakładasz, że jak ktoś
się włamie na serwer to od razu będzie miał dostęp do root’a, czy
ogólnie pełny dostęp do wszystkich zasobów na tym serwerze. Nie wiem
dlaczego nie bierzesz pod uwagę tego, że ktoś może się dostać np. tylko
do dumpa bazy.

… co zwykle równa się dostępowi do wszystkich innych plików. Szyfrowanie haseł imho miałoby sens, jeśli hasło byłoby np, pobierane z innego serwera poprzez jakieś api. I np. każde takie pobranie jest logowane, a wręcz wymaga zgody autoryzacyjnej i jest dozwolone np. tylko o pełnej godzinie (bo tak jest cron ustawiony) z konkretnego ip.

Co z tego że szyfrogram a nie hash. X znaków hasła + Y znaków soli. Nie
znasz długości ani hasła ani soli. Powiedz mi ile czasu więcej zajmie Ci
znalezienie co rzeczywiście jest hasłem w stosunku do hasła zapisanego w
czystej postaci?

Jeśli poznasz klucz szyfrujący? Maksymalnie tyle, ile znaków ma hasło+sól. A w praktyce mniej. Zakładając, że sól doklejasz z przodu, ma ona np. 20 znaków, to 21 pierwsza próba logowania już się powiedzie. Przyjmując, że atakujący nie zna Twojego algorytmu dodawania soli.

Sól dodaje się hashy po to, żeby zlikwidować podatność na rainbow tables. Nie rozumiem czemu uparłeś się na tym dodawaniu soli do haseł, które następnie są szyfrowane przy pomocy AES w tym wypadku.

Nie po to się szyfruje dane, żeby nikt nigdy nie złamał szyfru, bo
takich szyfrów nie ma, i nie będzie.

Polecam: http://en.wikipedia.org/wiki/One-time_pad

Mam dziwne wrażenie, że ta dyskusja nie prowadzi do niczego :wink:

Ta dyskusja prowadzi do niczego, bo uważasz, że skoro istnieje prawdopodobieństwo, że ktoś niepowołany może się dostać i do bazy i do secrets.yml, to jakakolwiek próba zabezpieczenia się w postaci szyfrowania przed “mniejszym” włamaniem nie ma sensu. Innymi słowy, po co zapinać pasy w samochodzie skoro możemy samochodem spaść w kilometrową przepaść.

Swoją drogą, po co nam taki One-Time Pad, skoro istnieje prawdopodobieństwo, że ktoś jednak przechwyci taki One-Time Pad? To już lepiej w ogóle wiadomości nie szyfrować bo to bez sensu…

Over and Out.

Enkryptowanie haseł w bazie danych ma jak najbardziej sens.
Skompromitowanie bazy danych to nie zawsze dostęp do systemu plików. Przykładem może tu być wyciąganie danych przez sql injection. Kolejna rzecz, to nawet jeśli dostaniemy dostęp do filesystemu (np. ktoś ustawi puste hasło dla użytkownika postgres) to nie znaczy to, że od razu mamy dostęp do całego filesystemu (czyt. zazwyczaj baza danych działa z innym ownerem niż aplikacja).

@essepl: kolejna rzecz to dlaczego przyjąłeś założenie, że baza danych stoi na tym samym serwerze? :wink:

@dedoel: cały mechanizm możesz dodatkowo wzmocnić ACL na serwerze, na którym będzie się uwierzytelniać tym hasłem. Mówiąc prościej serwer pozwala na uwierzytelnianie tylko z danego hosta/adresu ip. Pytanie, czy taka funkcjonalność jest wspierana.

1 Like

Muszę się zgodzić z @essepl

Jak uzyska ktoś dostęp do kodu, to pomoże ci jedynie asynchroniczne szyfrowanie, które w tym wypadku jest bezsensowane bo za kazdym razem, ze odszyfrować hasło, będziesz musiał podać jakieś dane, które albo będziesz wprowadzał ręcznie, albo dalej będą gdzieś zapisane. Więc koło się zamyka.

Może zamiast nie przyjmując do siebie że takie rozwiązanie jest bezsensowane, napisz dlaczego uważasz że tak powinno być.

Może dla tego że to dział pierwsza pomoc, a w większości prostszych stron jak jak w wielu aplikacjach (ale nie wszystkich), bazę umieszcza się na tym samym serwerze. No chyba że masz ten komfort, że pracujesz nad zaawansowanym systemem i baze trzymasz na innym serwerze.

Jak miło poczytać posty na techniczne tematy toczone w kulturalnej i nienerwowej atmosferze <3

2 Likes

Jednym z use case’ów to kiedy nie chcemy, aby dev, który nie ma dostępu do produkcji, ale pracuje na dumpach bazy, nie miał dostępu do tych haseł.

1 Like