Wpis z mikrobloga

Stworzyłem sobie własny, prywatny dyndns :D #chwalesie

O co chodzi?
Mam sobie domenę, którą trzymam na MyDevil i chciałbym kilka subdomen przekierować na swoje Raspberry Pi, które stoi u mnie w domu. Problem: moje IP jest zmienne (zmienia się rzadko, ale jednak). Mógłbym je aktualizować ręcznie przy zmianach... no ale jestem programistą, więc automatyzujemy ;)

Na hostingu postawiłem appkę w #python #flask. Appka ma za zadanie zaktualizować IP przypisane do domeny, kiedy dostanie odpowiednie zapytanie. Jest jeden haczyk: nie chcę, żeby każda losowa osoba z netu mogła mi zaktualizować adres. Potrzeba trochę kryptografii.

Rozwiązanie jest takie: na RPi mam parę kluczy RSA. Klucz publiczny jest skopiowany na hosting i ma do niego dostęp również appka, w której jest przypisany do mojej domeny.

Na RPi stoi zadanie, które co pół godziny wysyła do appki HTTP GET. Appka zwraca losowe 32 bajty zakodowane base64. Zadanie konstruuje wiadomość, złożoną z głównej domeny, subdomen do aktualizacji i tego losowego ciągu, i podpisuje ją kluczem prywatnym. Wiadomość i podpis trafiają do appki przez HTTP POST. Appka weryfikuje podpis kluczem publicznym przypisanym do domeny i jeśli jest ok, aktualizuje DNSy na adres, z którego przychodziły zapytania (oczywiście do weryfikacji używa wygenerowanego wcześniej, zapamiętanego losowego ciągu).

Mała rzecz, a cieszy, aż musiałem się pochwalić ( ͡ ͜ʖ ͡)

Jak ktoś ma hosting na MyDevil i chce zrobić coś podobnego, albo przerobić na jakiś inny hosting, albo cokolwiek... to kod appki jest tutaj: https://gitea.ebvalaim.pl/ebvalaim/devil-dyndns (nawiasem mówiąc, to jedna z tych aktualizowanych subdomen :P)

#programowanie
  • 10
@fizyk20: istnieje duże prawdopodobieństwo, że ktoś sobie może wylosować ten same bajty skoro losowanie masz równo co pół godziny. A później tylko atak ze znanym fragmentem tekstu jawnego. Wiadomości może sobie przechwycić bardzo dużo, każda podpisana tym samym kluczem, "losowy" ciąg tez będzie znany. Z kryptograficznego punktu widzenia słabe zabezpieczenie ;)
@sokytsinolop: Ale masz znany fragment tekstu jawnego i możesz sobie przechwycić wiele szyfrogramów w których będziesz znał fragment tekstu jawnego a każdy podpisany tym samym kluczem. Tyle wystarczy żeby to odszyfrować i odgadnąć twój klucz prywatny.
istnieje duże prawdopodobieństwo, że ktoś sobie może wylosować ten same bajty skoro losowanie masz równo co pół godziny


@Philopolemus_Fronius: Po pierwsze, generator liczb losowych nie jest seedowany tylko czasem (mam nadzieję - jak jest, to Crypto.Random jest słabszy, niż bym się spodziewał). Po drugie, to że ktoś inny je wylosuje, to nie problem - problem jest, jeśli appka wylosuje te same dwa razy (to tylko zabezpieczenie przeciwko replayowi podpisów).

A później
@fizyk20: Jak dla mnie - kryptograficznie (ideowo) rozwiązanie wydaje się okej.. Mam jedną uwagę do implementacji. W funkcji constructmessage masz:

return main_domain.encode("utf-8") + domains.encode("utf-8") + challenge
Jak budujesz wiadomość do podpisu, to koniecznie muszą być separatory pomiędzy konkatenowanymi elementami. Inaczej jest ryzyko, że dwie różne wiadomości mogą dać ten sam podpis. Wynika to z faktu, że np. "123"+"456" daje ten sam wynik co "12"+"3456".

Inne małe ryzyko jakie może tutaj
@securitymb: Dzięki za uwagi!

Jak budujesz wiadomość do podpisu, to koniecznie muszą być separatory pomiędzy konkatenowanymi elementami. Inaczej jest ryzyko, że dwie różne wiadomości mogą dać ten sam podpis. Wynika to z faktu, że np. "123"+"456" daje ten sam wynik co "12"+"3456".


Fakt, ma sens.

Inne małe ryzyko jakie może tutaj być, to jeśli ktoś odkryje Twój endpoint GET-owy, to może się wyzłośliwiać i ciągle do niego uderzać, powodując wygenerowanie nowego
Zadanie konstruuje wiadomość, złożoną z głównej domeny, subdomen do aktualizacji i tego losowego ciągu, i podpisuje ją kluczem prywatnym. Wiadomość i podpis trafiają do appki przez HTTP POST. Appka weryfikuje podpis kluczem publicznym przypisanym do domeny i jeśli jest ok


@fizyk20: a nie mogłeś po prostu zrobić zwykłego klucza autoryzacyjnego w nagłówku HTTP (np. X-Auth, albo nawet zwykłe Authorization: bearer XXX, albo najzwyklejsze login+pass) i użyć HTTPS? ( ͡
@morsik: Loginy i hasła później trzeba gdzieś trzymać, zaraz baza danych się przydaje i się robi bałagan. Tak mam plik klucza obok appki i tyle :P

A HTTPS w sumie już używam - nawet nie pomyślałem, że to załatwia już większość problemów, które rozwiązywałem niezależnie :P