Sockety - optymalność i bezpieczeństwo

Sockety - optymalność i bezpieczeństwo
Grzyboo
  • Rejestracja:ponad 9 lat
  • Ostatnio:4 miesiące
  • Postów:206
0

Mam pewne pytania dotyczące socketów. Ogólna idea mojej aplikacji jest taka: Serwer aktualizuje kilka plików co jakiś czas, a aplikacja w telefonie(client) ma te pliki mieć zawsze aktualne, czyli zgodne z serwerem. I tutaj pojawiają się pytania.

  1. Pliki mają kilka MB. Pobierać tyle z każdym włączeniem aplikacji nie jest chyba dobrym pomysłem. Na pewno nie byłoby, gdyby pliki urosły do rozmiaru 1GB. Pomysł mam taki, żeby każdej aktualizacji plików przez serwer przyporządkować numer odpowiadający dacie aktualizacji (sekundy, które upłynęły od 1970 roku czy coś) i ten numer wysyłać clientowi za każdym razem, gdy pobiera pliki. Przy włączeniu aplikacji client by wysyłał ten numer i gdy są równe to pliki nie zostaną wysłane i zaoszczędzimy kilka MB transferu. Pytanie: Jak realizować taki problem? Czy moje rozwiązanie jest sensowne i tak powinno się to robić?

  2. Inna sprawa to bezpieczeństwo. Nie widzę potrzeby, aby owe pliki były w pełni publiczne. Czy powinienem zastosować jakieś szyfrowanie? Jak wygląda sprawa z możliwością przechwycenia tych plików przez "kogoś z zewnątrz"? Gdybym zamiast mało istotnych plików przesyłał login i hasło do serwisu działającego na serwerze to konieczne by było jakieś konkretne szyfrowanie, czy może prosty algorytm typu RSA byłby wystarczającym zabezpieczeniem?

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2
  1. A nie prościej policzyć hash z tego pliku i wysłać tylko ten hash? ;)

prosty algorytm typu RSA

o_O ? Prosty to on jest chyba tylko w wersji textbook implementowany "na pałe" (i podatny na wszystkie możliwe side channele). Zresztą rozumiesz chyba ze RSA nie pozwala szyfrować danych wiekszych niż modulus? Do szyfrowania dużych danych stosuje się algorytmy symetryczne jak AES.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Grzyboo
Fakt, textbookowe wersje na pałę wyglądają na dosyć proste :D Może źle się wyraziłem, bo nie chciałem RSA tych plików gigowych szyfrować. Jednak fakt, dla szyfrowania haseł też by się nie sprawdził.
2

odp1.

Robisz hashsum na pliku i jeśli się nie zgadza u klienta, to znaczy, że ma stary plik.

Teraz żeby nie przesyłać przy aktualizacji całego pliku 1GB, to możesz dane mieć zapisane pewnymi blokami.

A dane mieć podzielone jak w drzewie binarnym.

Gdy hashsum wszystkiego się nie zgadza, to sprawdza, która połowa się nie zgadza i tak szukasz bloku, który cię interesuje.

Trochę się zminimalizuje transfer, ale nie wiem czy tak się robi komercyjnie.

Patryk Miszczak
Albo można zrobić coś podobnego jak w Gicie. Po stronie serwera mogłaby być przechowywana historia zmian i później zrobić różnicę między wersją która jest u użytkownika (wyciągając ją z historii na podstawie hashu), a która jest na serwerze i tylko ją wysłać.
Grzyboo
  • Rejestracja:ponad 9 lat
  • Ostatnio:4 miesiące
  • Postów:206
0

Ok, czyli wydedukowałem:

  1. Wysyłać hash pliku w celu ustalenia, czy plik jest spójny. Do tego mógłbym użyć algorytmów wyznaczania md5, sha-1. Tylko zadbać, żeby taki algorytm eliminował kolizje.
  2. Pliki warto zaszyfrować przez np. AES
edytowany 1x, ostatnio: Grzyboo
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0
  1. Ale znów: nie implementować tego samemu i nie robić tego na pałe. AESa też można łamać na wiele sposobów jeśli ktoś go źle używa i nie rozumie co robi.

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Patryk Miszczak
  • Rejestracja:około 8 lat
  • Ostatnio:około 2 lata
  • Lokalizacja:Poznań
  • Postów:13
1
  1. Nie lepsze byłoby stworzenie szyfrowanego połączenia? Java w standardzie ma możliwość tworzenia socketów korzystających z SSLa.
0

@Shalom,

Ale znów: nie implementować tego samemu i nie robić tego na pałe. AESa też można łamać na wiele sposobów jeśli ktoś go źle używa i nie rozumie co robi.

  1. Czy możesz rozwinąć trochę?
  2. Co masz na myśli, mówiąc, że AESa można łamać na wiele sposobów? Możesz podać jakieś konkretne- oczywiście chodzi o słowa-klucze.
  3. Co to znaczy używać na pałę?
    Wiadomo, że własnej implementacji się nie robi. Masz na mysli tylko to? Pomijamy skrajności typu wektorem IV jest klucz albo klucz jest jawny.
  4. Np., czy widzisz jak można łatwo coś spieprzyć używając AESa z OpenSSLa?

I w sumie drugie pytanie. Powiedzmy, że potrzebujemy generować sporo kluczy symetrycznych. Skąd wziąć jakiś pewny generator pseudolosowy i co najważniejsze, być pewnym, że jest bezpiecznie?

edytowany 1x, ostatnio: Shalom
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Ataków na AESa jest sporo. Jeśli implementujesz samodzielnie to oczywiście jest kupa ataków side-channel pozwalajacych odzyskać klucz prywatny (ataki na cache, memory deduplication, power analysis i wiele innych). Z drugiej strony nawet używając jakiegoś OpenSSL może mocno zawalić sprawę jeśli nie rozumiesz co robisz.
https://github.com/p4-team/ctf/tree/master/2015-10-18-hitcon/crypto_100_simple atak na AES-CFB
https://github.com/p4-team/ctf/tree/master/2016-03-12-0ctf/peoples_square atak na AES ze zmniejszoną liczbą rund
https://github.com/p4-team/ctf/tree/master/2016-09-16-csaw/neo atak Padding Oracle na AES-CBC (swego czasu dość popularna podatność jeśli sygnalizujesz użytkownikowi że deszyfrowanie się nie powiodło)
https://github.com/p4-team/ctf/tree/master/2017-03-18-0ctf-quals/integrity forgery przez bitflipping AES-CBC
https://github.com/p4-team/ctf/tree/master/2017-02-12-bsidessf/delphi forgery przez bitflipping AES-CBC
https://github.com/p4-team/ctf/tree/master/2016-01-16-insomnihack/crypto_200_fridginator deszyfrowanie części wiadomości szyfrowanej przez AES-ECB a następnie forgery w trybie AES-ECB


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
0

https://github.com/p4-team/ctf/tree/master/2016-09-16-csaw/neo atak Padding Oracle na AES-CBC (swego czasu dość popularna podatność jeśli sygnalizujesz użytkownikowi że deszyfrowanie się nie powiodło)

Czyli co to znaczy? Że AES-CBC jest niebezepieczny? Widziałem inne publikacje, które potwierdzają jego bezpieczeństwo. Więc w końcu nie wiem. Bo przecież nie można opierać się na informowaniu usera. Bo nawet jeżeli nie informujemy to co to daje? I tak się może domyślić. O co chodzi w tym nieinformowaniu?

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Jeśli informujesz użytkownika że deszyfrowanie się nie powiodło, to AES-CBC nie jest bezpieczny bo można właśnie tak jak w tekście wyżej użyć tzw padding-oracle i deszyfrować sobie dane w dość prosty sposób.
Chodzi o to że użytkownik nie powinien móc odróżnić błędu deszyfrowania od błędnych danych. Jeśli np. masz podać gdzieś zaszyfrowany ciąg np. z loginem i hasłem i serwer je odszyfrowuje i próbuje użyć do logowania to zarówno błąd deszyfrowania jak i błędne dane powinny dać taki sam error.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
jarekczek
Fajny wątek, tylko z użyciem ataku thread-hijacking :)
0

Ja nie rozumiem jaki to ma sens. Żeby odpowiedź 'deszyfracja nie powiodła się' miała jakąkolwiek sens, aplikacja deszyfrująca musi dysponować poprawnym kluczem. Jeżeli użytkownik ma taki klucz (jego aplikacja) ma, to dlaczego to w ogóle jest uznawane za atak.

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

A kto powiedział że to użytkownik ma dostęp do klucza? :) Wyobraź sobie że wchodzisz na stronę która w cookie zapisuje jakieś zaszyfrowane dane. Strona może je spokojnie odszyfrować z cookie, ale ty nie.
Pamiętaj też o tym że są ataki MITM gdzie ktoś może przechwycić zaszyfrowany strumień danych a wcale nie ma klucza.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
0

Ciągle Cię nie rozumiem.

Chodzi o to że użytkownik nie powinien móc odróżnić błędu deszyfrowania od błędnych danych.

Dobrze. Mamy serwer X. Aplikacja Y wysyła dane zaszyfrowane. W ogólności w takiej komunikacji masz dwa scenariusze:

  1. Serwer odszyfrował poprawnie, klucz był dobry, zwraca np. 200
  2. Serwer nie zdołał odszyfrować, bo Y nie ma klucza i "robi sobie jaja". Co może zrobić serwer? Może grać głupa, i mówić, że dane niepoprawne zamiast obwieścić miastu i światu, że nie udało się zdeszyfrować. Ale czy to cokolwiek daje? Czy trzeba dużej przenikliwości, że zgadłem jednak nieprawidłowo klucz, tj. były problemy z deszyfracją a nie żadne tam błędne dane?
xfin
  • Rejestracja:ponad 11 lat
  • Ostatnio:8 miesięcy
  • Lokalizacja:Genewa
  • Postów:597
0
Biały programista napisał(a):

Ciągle Cię nie rozumiem.

Nie rozumiesz, bo widzę, że pominąłeś ważną kwestię oraz podałeś banalny przykład, gdzie ominąłeś clue sprawy. I to nie chodzi o to, że "serwer zrobi głupa" i błędnie coś policzy.
@Shalom opisał już wcześniej przykład:

masz podać gdzieś zaszyfrowany ciąg np. z loginem i hasłem i serwer je odszyfrowuje i próbuje użyć do logowania to zarówno błąd deszyfrowania jak i błędne dane powinny dać taki sam error

I tutaj użytkownik nie może posiadać wiedzy co poszło nie tak, po prostu to za bardzo narusza bezpieczeństwo.
Czy serwer powinien radośnie komunikować, co poszło nie tak?

Spójrz: zarówno w przypadku podania błędnych danych logowania, jak i użycia złego klucza użytkownik otrzyma taki sam error. I tak być powinno. Nie wiesz co poszło nie tak.

Jeśli masz serwer, który traktuje ww. przypadki osobno i udostępnisz informację Błąd deszyfrowania, to potencjalny kradziej już wie, że musi szukać innego klucza. Jak w końcu go znajdzie to otrzyma informację Błędne dane. I co? Ma kolejną cegiełkę wiedzy, że trafił na dobry klucz. A ten fragment wiedzy otrzymał bezpośrednio od serwera (czy tam od programisty, który ten soft napisał).
Teraz zostanie kradziejowi tylko szukanie nazwy użytkownika i hasła.

Oczywiście szukanie klucza, czy tam loginów i haseł ma większą/mniejszą trudność, niemniej każda niepotrzebna informacje tylko wpływa na podatność na potencjalny atak.

nalik
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 2 lata
  • Postów:1039
0
Grzyboo napisał(a):
  1. Pliki mają kilka MB. Pobierać tyle z każdym włączeniem aplikacji nie jest chyba dobrym pomysłem. Na pewno nie byłoby, gdyby pliki urosły do rozmiaru 1GB. Pomysł mam taki, żeby każdej aktualizacji plików przez serwer przyporządkować numer odpowiadający dacie aktualizacji (sekundy, które upłynęły od 1970 roku czy coś) i ten numer wysyłać clientowi za każdym razem, gdy pobiera pliki. Przy włączeniu aplikacji client by wysyłał ten numer i gdy są równe to pliki nie zostaną wysłane i zaoszczędzimy kilka MB transferu. Pytanie: Jak realizować taki problem? Czy moje rozwiązanie jest sensowne i tak powinno się to robić?

Czemu nie rozdzielić tego na 2 części:

  • Serwis metadanych, który trzyma informacjie o plikach - struktura, timestampy. Być może daloby się wykorzystać ZooKeeper albo etcd.
  • Storage plików, z dostępem przez sftp albo scp. Na początek zwykły serwer powinien wystarczyć.

Aplikacja kliencka odpytywałaby serwer metadanych o zmiany a następnie sama decydowała co pobrać.

edytowany 2x, ostatnio: nalik
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

@Biały programista zakładasz blędnie że ktoś tu próbuje "zgadywać klucz", co nie ma wcale miejsca. Ze względu na sposoby działania niektórych algorytmów szyfrowania można robić różne ciekawe rzeczy nie znając klucza. Szyfry blokowe w trybie CBC działają tak, że blok tekstu jawnego jest xorowany z poprzednim blokiem tekstu zaszyfrowanego i dopiero te dane są szyfrowane. Analogicznie deszyfracja wygląda tak, że najpierw deszyfrujesz dane (np. jakimś AESem) a potem xorujesz je z poprzednim zaszyfrowanym blokiem, zeby odzyskać tekst jawny.
Dla pierwszego bloku xor jest wykonywany z IV (bo nie ma "poprzedniego" bloku). Jak nie trudno zauważyć, można w takim razie zmienić IV albo któryś kolejny blok tekstu zaszyfrowanego i spowoduje to zmianę wartości do której deszyfruje się kolejny blok, bo xor wykona się z czymś innym.
Jeśli ktoś rozumie jak działa XOR to łatwo zauważyć że możemy w praktyce wymusić deszyfrowanie się bloku do zupełnie dowolnej wartości, jeśli znamy dla tego bloku tekst jawny. Wystarczy ze zrobimy IV[i] = IV[i] xor plaintext[i] xor expected_plaintext[i] i voila.
Tą technike można wykorzystać do modyfikowania deszyfrowanej wiadomosci, bez znajomości klucza. Można ją też wykorzystać do padding oracle attack.

Zgadywanie klucza nie ma tu nic do rzeczy ;)


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
0
Grzyboo napisał(a):
  1. Pliki mają kilka MB. Pobierać tyle z każdym włączeniem aplikacji nie jest chyba dobrym pomysłem. Na pewno nie byłoby, gdyby pliki urosły do rozmiaru 1GB. Pomysł mam taki, żeby każdej aktualizacji plików przez serwer przyporządkować numer odpowiadający dacie aktualizacji (sekundy, które upłynęły od 1970 roku czy coś) i ten numer wysyłać clientowi za każdym razem, gdy pobiera pliki. Przy włączeniu aplikacji client by wysyłał ten numer i gdy są równe to pliki nie zostaną wysłane i zaoszczędzimy kilka MB transferu. Pytanie: Jak realizować taki problem? Czy moje rozwiązanie jest sensowne i tak powinno się to robić?

Tutaj można zastosować jeszcze inny mechanizm, zapamiętujesz najnowszą wersje pliku i zapamiętujesz metadane zmian w formie wersja X dodanie Y bajtów w pozycji Z
Teraz klient wysyła do serwera info że posiada plik w wersji V(tylko numer wersji). Serwer na tej podstawie zwraca informacje jakie operacje należy wykonać na pliku żeby uzyskać taki sam plik jak na serwerze. Klient po wykonaniu tej operacji aktualizuje numer wersji pliku do najnowszej.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)