Pytanie:
Bezpieczne wysyłanie wysokiego wyniku po stronie klienta na serwer
StationaryTraveller
2017-01-15 15:45:41 UTC
view on stackexchange narkive permalink

Tworzę aplikację internetową, która zawiera prostą grę javascript. Gdy gracz zakończy grę, najlepszy wynik jest wysyłany na serwer i zapisywany.

Po określonym czasie gracz z najlepszym wynikiem otrzymuje nagrodę.

Czy istnieje sposób na bezpieczne przesyłanie najlepszych wyników i zapobieganie wysyłaniu przez klienta „fałszywych” wyników?

Obecnie używamy:

  • Https.
  • Losowy token serwera przed każdą grą i wysyłany po zakończeniu gry wraz z wynikiem.
Nie ma niezawodnego sposobu rozwiązania tego problemu.Jedynym sposobem jest śledzenie indywidualnych wyników każdej gry na serwerze.
TLS nie ma tu nic do zrobienia i nie możesz zapewnić niczego po stronie klienta, jeśli * próbuje * być złośliwy.Przeczytaj [odpowiedź na temat twojego aktualnego problemu] (http://security.stackexchange.com/a/147047/91111).
Jest tu podobne pytanie, najlepsza odpowiedź zawiera kilka dobrych sugestii.https://stackoverflow.com/questions/73947/what-is-the-best-way-to-stop-people-hacking-the-php-based-highscore-table-of-a-f
Swoją drogą, zadajesz to pytanie * o wiele * za późno.Gdyby było to wymagane, takie zabezpieczenie powinno być wbudowane od samego początku, a nie wszczepiane później.
OTOH, jeśli motywacja do złamania gry (a więc fałszywe wysokie wyniki) jest mniejsza niż trudność w złamaniu jej, Twoja gra może się dobrze sprawdzić po prostu dlatego, że nie ma wystarczającego zainteresowania fałszowaniem wyniku.
Sześć odpowiedzi:
grc
2017-01-15 16:54:50 UTC
view on stackexchange narkive permalink

Serwer nie może w pełni ufać żadnym danym, które otrzymuje od klienta, więc sprawdzenie najlepszych wyników jest trudne.

Oto kilka opcji:

  1. Ukryj kod po stronie klienta i ruch na serwerze. To najłatwiejsza opcja - nadal będzie można oszukiwać, ale prawdopodobnie nie będzie to nic warte.

  2. Wyślij pełną lub częściową powtórkę gry na serwer do walidacji. Ruchy gracza mogą być uruchamiane na serwerze, aby określić prawidłowy wynik. To zadziała w niektórych grach, a nie w innych.

  3. Przenieś logikę gry i weryfikację na serwer. Klient po prostu przekazuje każdy ruch na serwer, gdzie jest sprawdzany, a stan gry aktualizowany.

Wszystko sprowadza się do tego, jak działa Twoja gra, jakie jest prawdopodobieństwo, że ludzie będą oszukiwać i jak bardzo zależy ci na tym.

# 3 to jedyny właściwy sposób, aby to zrobić
@theonlygusti Może źle zrozumiałem, ale nie musisz przenosić logiki gry - wystarczy, że powielę ją na serwerze.Jeśli wszystko, co wyślesz, to wszystkie dane wejściowe gracza, serwer może je odtworzyć i zweryfikować wynik.Wtedy musisz tylko dbać o graczy „TASbot” :).Na przykład gry, która robi to dobrze - DROD.Ponieważ jest to gra logiczna, jest również odporna na rozgrywki wspomagane narzędziami.Jedynym niemożliwym do naprawienia problemem jest snajperka, w której ktoś ogląda demo innego gracza i szuka punktów optymalizacji.
@Maurycy Właśnie mówiłem, że jedynym sposobem na upewnienie się, że najlepszy wynik jest prawidłowy, jest obsłużenie gry na serwerze.Przenoszenie / replikowanie tak naprawdę nie ma znaczenia
@theonlygusti Mam na myśli to, że chodzi o to, że „przesuń logikę gry” i czułem, że trzeba się dziwić, że wystarczy to powtórzyć.Prawdopodobnie powinienem był oznaczyć Cię w komentarzu, ponieważ naprawdę chciałem odpowiedzieć na całą odpowiedź, a nie na Twój komentarz :)
@theonlygusti: W przypadku wielu typów gier 2 jest tak samo dobre jak 3.
@theonlygusti Correction, nr 3 to jedyny * niezawodny * sposób, aby to zrobić (ale to w rzeczywistości nie jest prawdą, ponieważ nie jest niezawodny!).To po prostu najbardziej niezawodna i najtrudniejsza z podanych opcji.
@theonlygusti, do gier deterministycznych (myślę: Tetris), numer 2 będzie działał, o ile nie masz nic przeciwko przyznawaniu rekordów wysokiego wyniku AI.
@Mark # 2 ma również wadę, którą klient może zoptymalizować w oparciu o przyszłą wiedzę.Na przykład.w Tetris, jeśli znasz wszystkie elementy, które dostaniesz, możesz znaleźć lepszą strategię niż w przypadku zdobycia tylko jednego elementu, a następnie umieść go gdzieś, a następnie zdobądź następny.
# 1 jest bezużyteczny w grze javascript, ponieważ jest _ znacznie_ łatwiejsze do ponownego wygenerowania czytelnego kodu niż w jakimkolwiek innym języku.
Philipp
2017-01-15 16:54:58 UTC
view on stackexchange narkive permalink

Gdyby osoba atakująca była atakującym pośrednikiem w warstwie sieciowej, wystarczyłby protokół https. Ale niestety twój atakujący jest klientem, więc jest to raczej bezcelowe.

Zasada numer jeden w grach zabezpieczających przed oszustwami: Nigdy nie ufaj klientowi! Klient jest w rękach wroga.

Gry Javascript uruchamiane są w przeglądarce internetowej użytkownika. Jak zapewne wiesz jako programista stron internetowych, każda przeglądarka internetowa jest obecnie wyposażona we wbudowany debugger, który może wyświetlać i zmieniać wszystkie zmienne podczas działania aplikacji. Użytkownik może po prostu użyć debugera, aby zmienić swój wynik przed przesłaniem. Nic nie możesz zrobić, aby temu zapobiec. W przypadku gier przeglądarkowych nie możesz nawet nałożyć na nie narzędzia przeciwdziałającego oszustwom innej firmy (które i tak mają wątpliwą wartość i są wątpliwe etycznie).

Jedynym środkiem zaradczym jest wdrożenie wszystkich mechanizmów gry wartych manipulacji na serwerze. Klient powinien jedynie przekazywać polecenia użytkownika na serwer i wizualizować rozgrywkę na podstawie komunikatów serwera. Właściwa rozgrywka powinna odbywać się na serwerze, gdzie jest poza zasięgiem oszustów.

Tak, oznacza to, że będziesz musiał przeprojektować architekturę oprogramowania swojej gry od podstaw. Oznacza to również, że będziesz musiał dodać kod przewidywania i interpolacji, aby opóźnienie sieci było mniej widoczne. Oznacza to również, że będziesz potrzebować znacznie lepszego sprzętu serwerowego i lepszego połączenia internetowego dla swojego serwera (serwerów). Ale jeśli chcesz grę online bez oszustw, to jedyna opcja.

Jest typowe zaufanie **, ale odpowiedź zweryfikuj ** - zobacz opcję nr 2 w odpowiedzi grc.
@MSalters Czy to nie ** zaufanie, ale weryfikacja ** oksymoronu?Nie ufasz klientowi, dlatego weryfikujesz jego odpowiedź.Jeśli zaufałeś klientowi, po co to weryfikować?
@Tom „Zaufaj, ale sprawdź” to powszechne wyrażenie pochodzące z rosyjskiego przysłowia (patrz [Wikipedia] (https://en.wikipedia.org/wiki/Trust,_but_verify)).I tak, jest oksymoroniczny, ale można go też odczytać jako „niewinny, chyba że udowodniono mu winę”.Lub, odpowiednio, kiedy Wikipedia zakłada, że użytkownicy działają w dobrej wierze podczas edycji (jest to tylko wiki, ponieważ nie jest zablokowana), ale nadal wymaga od nich cytowania odniesień.
Lie Ryan
2017-01-15 22:29:01 UTC
view on stackexchange narkive permalink

Aby osiągnąć wysoki wynik w bezpiecznej grze, potrzebujesz „ dowodu pracy” lub raczej, bardziej trafnie, zwanego dowodem gry.

Dowód pracy / play to wszelkie dane, które są trudne do obliczenia przed zakończeniem gry, ale łatwe do obliczenia po zakończeniu gry i łatwe do zweryfikowania przez serwer. Na przykład w przypadku gry Sudoku dowodem wykonania jest rozwiązanie łamigłówki.

Niestety, nie ma ogólnego sposobu na zintegrowanie odpowiedniego systemu weryfikacji gry w wielu grach. Nie zawsze jest możliwe zintegrowanie dowodu gry bez poprawiania lub ponownego przeglądania rozgrywki lub ograniczania zakresu tabeli wyników tylko do elementów, w których można dołączyć wystarczająco bezpieczny dowód gry.

Dowód gry na gra rozpoczyna się od wydania przez serwer seeda dla RNG gry. Klient będzie musiał wtedy znaleźć dowód gry, który pasuje do materiału siewnego, który został wydany graczowi. W wielu grach dowód gry można utworzyć, przesyłając rozwiązanie gry na serwer wraz z przesyłaniem najlepszych wyników, w innych może być konieczne nagranie całej sesji gry na różnych poziomach szczegółowości w zależności od gry i dowodu gry, której używasz.

Dowód gry musi być odporny na powtórki (jeden gracz nie powinien być w stanie użyć ukończonej gry innego gracza, aby ułatwić obliczenie własnego dowodu gry). Ogranicza to dowód gry do gier, w których istnieje pewna przypadkowość, że gracze nie mogą po prostu ponownie wykorzystać dowodu gry innego gracza, ale także nie mogą mieć zbyt wielu niedeterministycznych zachowań do tego stopnia, że ​​weryfikacja gry staje się niemożliwa.

Dowód gry jest również ograniczona. Na przykład w grze Sudoku nie można udowodnić, ile czasu zajmuje graczowi rozwiązanie łamigłówki. Dowód gry nie zawsze też może odróżnić grę, w którą gra sam gracz, od gracza, który napisał scenariusz, który grał za niego.

Jednym ze sposobów zapobiegania „plagiatowi” rozwiązań byłoby określenie nazwy gracza przed rozpoczęciem gry i zaszyfrowanie ziarna losowego zgodnie z tą nazwą.i niech gra zgłosi niezaszyfrowane ziarno wraz z nazwą i rozwiązaniem.
Ilość czasu jest łatwa do śledzenia, ponieważ ** mamy ** tutaj stronę serwera.Jest to kwota między wygenerowaniem układanki a przekazaniem wyniku.
CR Drost
2017-01-16 00:15:32 UTC
view on stackexchange narkive permalink

Chciałem tylko wspomnieć, że istnieje rozwiązanie tego problemu, ale prawdopodobnie nie będzie ono dostępne dla Ciebie; to rozwiązanie nazywa się „szyfrowaniem homomorficznym” i pozwala klientowi wykonać znane obliczenia bez dokładnej wiedzy, z jakimi wartościami oblicza, a serwerowi w związku z tym sprawdzić strukturę obliczonej wartości, aby udowodnić, że klient nie tylko wysyła losowy ciąg z powrotem, ale w rzeczywistości zbudował go z kilku podanych wartości.

Problem w tym, że jest albo powolny albo niekompletny , z „niepełnym” znaczeniem „nie zawiera pełnego zakresu logicznych prymitywów”. Bardzo często jest to częściowy system pozwalający na pewne operacje szyfrowania i deszyfrowania E (), D (), a także pewne skomplikowane operacje ⊕ takie, że

D (E (A) ⊕ E (B)) = A + B,

lub tym podobne.

Zobaczmy, jak to rozwiązuje problem w niektórych grach. Rozważ grę typu „gas out”, w której naciskasz N heksów sześciokątnej siatki i każdy z nich przełącza zarówno swój stan, jak i stany osób wokół niego. Jest to algebra przemienna na tych „tłoczeniach”, a zatem w danym rozwiązaniu nie będzie więcej niż N naciśnięć łącznie, a każdy heks zależy tylko od stanu początkowego plus naciśnięcia jego własnego heksa plus 6 heksów wokół niego.

Ponieważ nasz schemat szyfrowania homomorficznego dopuszcza tylko +, a nie XOR, dajemy każdemu szesnastkowemu 3-bitowy licznik określający, ile razy został odwrócony. (Oprogramowanie klienta automatycznie zmniejszy każde dwukrotne naciśnięcie klawisza szesnastkowego do zaledwie jednego naciśnięcia.) Rzeczywiste działania odwracania mają zatem wygląd wektorów bitowych,

  001 001 000 000 000 001 001 001 000 001 001 000 000 ... 000 00000000 00000001  

Innymi słowy, mają jedynki w każdym z tych 3-bitowych pól, które zmienia, plus 1 w 16-bitowym liczniku.

Szyfrujemy to wszystko za pomocą homomorficznego schematu szyfrowania, wysyłamy każdy z nich do klienta, a klient odsyła nam zaszyfrowaną wartość obliczoną na podstawie tych zaszyfrowanych wartości, które odesłaliśmy. Następnie odszyfrowujemy to i odszyfrowaną wartość za pomocą łańcucha bitów,

  001 001 001 001 ... 001 11111111 00000000  

i porównać z początkową grą -stan połączony z 0 dla tych 8 bitów licznika.

Jeśli wysyłają nam losową wartość, ich szansa, że ​​ją zaakceptujemy, wynosi 2 - (N + 8) , a zatem ich Jedynym użytecznym sposobem zaliczenia testów jest użycie wartości, które im podaliśmy w dozwolonej kombinacji. Mają dostęp do niektórych ruchów, na które nie pozwalamy im bezpośrednio z powodu przepełnienia liczb całkowitych, ale zawsze możemy zrobić pola szersze niż 3 bity, aby uczynić je bardziej kosztownymi dla licznika po prawej stronie. Ale nigdy nie przesyłano nam ich indywidualnych naciśnięć przycisków, a tym bardziej nie odtwarzaliśmy historii: zaakceptowaliśmy wektor mówiący „oto jak odwróciłem siatkę”, co jest „bardzo niepewną rzeczą”, przed którą wszyscy cię ostrzegają, ale my zrobili to w taki sposób, że nie mogą robić rzeczy, o które się martwimy, bez dostępu do tajnego klucza.

Zamiast tego w głosowaniu kryptograficznym widzisz tego rodzaju rzeczy, w których chcesz mieć pewność, że maszyna do głosowania nie daje Alice spontanicznie 1000 głosów.

Nie rozumiem, dlaczego szyfrowanie jest tutaj pomocne.Jedynym sposobem upewnienia się, że klient faktycznie rozwiązał zagadkę, jest dołączenie „dowodu pracy”, który wykonał.Jaka to różnica, jeśli dowód pracy nie był zaszyfrowany?
@AgnishomChattopadhyay Czy przychodzi Ci do głowy sytuacja, w której dowód działania jakiegoś rozwiązania S jest znacznie dłuższy niż samego S?Dzięki szyfrowaniu homomorficznemu w zasadzie nie musisz.
OscarAkaElvis
2017-01-15 16:04:08 UTC
view on stackexchange narkive permalink

Wszystko po stronie klienta może zostać sfałszowane. Więc odpowiedź brzmi nie.

EDYTUJ Usunąłem mechanizm bezpieczeństwa, który tutaj napisałem, ponieważ zapewnia on tylko sesje morskie ... ale sfałszowane wyniki mogą być wysyłane przez sesje morskie. Dzięki @Luke Park

Nie dostałem twojego drugiego akapitu.Powiedzmy, że trzymam „losowy” token po stronie serwera.Jak mogę to potwierdzić, gdy klient przesyła wynik? A w trzecim akapicie, co masz na myśli, mówiąc bezpiecznie wysyłając początkowy losowy token?
Wyślij go po stronie serwera oznacza, że jeśli używasz na przykład php, musisz wysłać go za pomocą php na zapleczu, a nie przez js.Wydaje mi się, że klienci nie są w stanie niczego wąchać i jeśli używasz https, jak powiedziałeś, wystarczy.Aby to zweryfikować, należy odebrać i przechowywać początkowy token (w bazie danych w sesji lub gdziekolwiek) na serwerze punktacji, a następnie, po otrzymaniu tokena klienta (który może zostać sfałszowany), należy porównać z początkowym wysłanym tokenem (który jest zabezpieczony), więcnie ma możliwości oszukania.
Sam powiedziałeś, że wszystko po stronie klienta może zostać sfałszowane.Pozostała część Twojej odpowiedzi jest zatem niepotrzebna.
@Luke Park, zapytał: `` Czy istnieje sposób na bezpieczne przesyłanie najlepszych wyników i zapobieganie wysyłaniu przez klienta 'fałszywych' wysokich wyników? '', Więc próbuję wyjaśnić cały proces
Nie ma całego procesu.Nie możesz temu zapobiec.Wszystko, co robi legalny klient, może zostać sfałszowane przez nielegalnego klienta.
Mylisz się.Chodzi o to, że serwer może utworzyć początkowy token dla gry, który jest wysyłany w zapleczu do serwera wyników.Ten token jest BEZPIECZNY.Następnie, po grach, token klienta może zostać sfałszowany, ok, ale mechanizm bezpieczeństwa polega na tym, że token wysłany przez klienta musi pasować do bezpiecznego tokena wysłanego jako pierwszy podczas tworzenia gry.
Ale klient nadal przesyła swój wynik na serwer, prawda?Z tokenem?
Pozwól nam [kontynuować tę dyskusję na czacie] (http://chat.stackexchange.com/rooms/51820/discussion-between-oscarakaelvis-and-luke-park).
Po chwili głębszego zastanowienia myślę, że masz rację Luke Park, przepraszam.Zmieniłem odpowiedź.
Ben Harrison
2017-01-18 22:09:42 UTC
view on stackexchange narkive permalink

Moje zalecenie dotyczy raczej techniki zaciemniania obrazu i może być frustrującą przeszkodą dla wielu użytkowników. Jednak zaawansowani lub zdeterminowani użytkownicy mogą nadal analizować kod źródłowy w celu odtworzenia wyników.

Użyj narzędzia takiego jak Hashids, aby utworzyć skrót wyniku i wyślij go w żądaniu serwera wraz z wynikiem w postaci zwykłego tekstu. Wartość ciągu identyfikatora użytkownika może być solą używaną do kodowania hashidu wyniku, co sprawi, że hash będzie bezużyteczny, jeśli zostanie udostępniony. Po stronie serwera możesz zdekodować ten hash i porównać wynik z wynikiem w postaci zwykłego tekstu, który został wysłany, aby upewnić się, że są zgodne z oczekiwaniami.

Chciałem zauważyć, że hashidy to tylko jedno narzędzie, którego można użyć.Jedynym ograniczeniem tej konkretnej biblioteki jest to, że nie obsługuje ona liczb ujemnych (zakładając, że Twoja gra może tego potrzebować).
Jest to tylko trochę lepsze niż wysłanie zwykłego tekstu, ponieważ użytkownik zna swój identyfikator i może go zdekodować, tak jak robi to serwer.


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...