Invio di un punteggio elevato lato client a un server in modo sicuro [duplicato]

39

Sto creando un'applicazione web che contiene un semplice gioco javascript. Una volta che il giocatore ha terminato di giocare, il punteggio più alto viene inviato al server e salvato.

Dopo un determinato periodo, il giocatore con il miglior punteggio riceve un premio.

Esiste un modo per inviare il punteggio elevato in modo sicuro e impedire al client di inviare "falsi" punteggi alti?

Attualmente stiamo usando:

  • Https.
  • Token casuali del server prima di ogni partita e inviati dopo che il gioco è finito insieme al punteggio.
posta StationaryTraveller 15.01.2017 - 10:45
fonte

6 risposte

111

Il server non può fidarsi completamente dei dati che riceve dal client, quindi la convalida dei punteggi più alti è difficile.

Ecco alcune opzioni:

  1. Offuscare il codice lato client e il traffico verso il server. Questa è l'opzione più semplice: sarà comunque possibile imbrogliare, ma probabilmente non varrà la pena per nessuno.

  2. Invia una replica completa o parziale del gioco al server per la convalida. Le mosse del giocatore possono essere eseguite sul server per determinare il punteggio legittimo. Questo funzionerà per alcuni giochi e non per altri.

  3. Sposta la logica di gioco e la convalida sul server. Il client trasmette semplicemente ogni mossa al server, dove viene convalidato e lo stato del gioco aggiornato.

Dipende dal modo in cui funziona il tuo gioco, dalla probabilità che le persone imbrogli e di quanto ti interessi se lo fanno.

    
risposta data 15.01.2017 - 11:54
fonte
27

Se il tuo attaccante fosse un attaccante man-in-the-middle sul livello di rete, allora sarebbe sufficiente https. Ma sfortunatamente il tuo aggressore è il cliente, quindi questo è piuttosto inutile.

Regola numero uno di giochi di cheat: Non fidarti mai del client! Il cliente è nelle mani del nemico.

I giochi Javascript vengono eseguiti nel browser web dell'utente. Come sicuramente sai come uno sviluppatore web, ogni browser web oggi ha un debugger integrato che può visualizzare e modificare tutte le variabili mentre un'applicazione è in esecuzione. L'utente può semplicemente utilizzare il debugger per modificare il proprio punteggio prima che venga inviato. Non c'è niente che puoi fare per impedirlo. Con i giochi basati su browser, non puoi nemmeno usare uno strumento anti-cheat di terze parti (che sono di dubbia utilità ed eticamente discutibili comunque).

L'unica contromisura è implementare tutte le meccaniche di gioco che valgono la pena di manipolare sul server. Il client non dovrebbe fare altro che inoltrare i comandi dell'utente al server e visualizzare il gameplay in base ai messaggi del server. Il gameplay effettivo dovrebbe accadere sul server in cui è fuori dalla portata degli imbroglioni.

Sì, questo significa che dovrai ridisegnare l'architettura del software del tuo gioco da zero. Significa anche che dovrai aggiungere un po 'di codice di previsione e di interpolazione per rendere il ritardo di rete meno visibile. E significa anche che avrai bisogno di un hardware server molto migliore e una migliore connessione internet per i tuoi server. Ma quando vuoi un gioco online privo di cheat, questa è l'unica opzione.

    
risposta data 15.01.2017 - 11:54
fonte
17

Per ottenere un punteggio elevato per il gioco sicuro, ciò di cui hai bisogno è " prova di lavoro " , o meglio, più appropriatamente chiamato proof of play.

Una prova di lavoro / gioco è qualsiasi dato che è difficile da calcolare prima di finire il gioco, ma facile da calcolare una volta che hai finito il gioco ed è facile da verificare dal server. Ad esempio, per un gioco di Sudoku, una prova di lavoro è la soluzione al puzzle.

Sfortunatamente, non esiste un modo generico per integrare una prova adeguata del sistema di gioco in molti giochi. Non è sempre possibile integrare una prova di gioco senza modificare o rehauling il gioco, o limitando l'ambito della classifica a solo elementi in cui è possibile includere prove di gioco sufficientemente sicure.

La prova di gioco su un gioco inizia dal server che rilascia il seme per l'RNG del gioco. Il cliente dovrà quindi trovare una prova di gioco che corrisponda al seme che il giocatore è stato rilasciato. In molti giochi, è possibile formulare una prova di gioco presentando la soluzione del gioco al server con la presentazione del punteggio più alto, in altri potrebbe essere necessario registrare l'intera sessione di gioco in vari livelli di dettagli a seconda del gioco e della prova di suonare che stai usando.

Una prova di gioco deve essere resistente alla replay (un giocatore non dovrebbe essere in grado di utilizzare il gioco finito di un altro giocatore per rendere più semplice la propria prova di gioco). Questo limita la prova del gioco ai giochi in cui c'è un po 'di casualità che i giocatori non possono semplicemente riutilizzare le prove di gioco di un altro giocatore, ma anche non può avere troppi comportamenti non deterministici al punto in cui la verifica del gioco diventa impossibile.

Anche la prova di gioco è limitata. Ad esempio, in un gioco Sudoku, non è possibile dimostrare la quantità di tempo che il giocatore impiega per risolvere il puzzle. Anche la prova di gioco non può sempre distinguere tra il gioco giocato dal giocatore stesso e il giocatore che ha scritto una sceneggiatura che ha giocato il gioco per loro.

    
risposta data 15.01.2017 - 17:29
fonte
8

Volevo solo menzionare che esiste una sorta di soluzione a questo problema, ma è probabile che non sia disponibile per te; la soluzione è chiamata "crittografia omomorfica" e consente a un client di eseguire un calcolo noto senza sapere esattamente quali valori stanno calcolando, e un server per verificare quindi la struttura del valore calcolato per dimostrare che il client non solo invia una stringa casuale indietro ma in realtà lo ha costruito tra i diversi valori forniti.

Il problema è che è lento o incompleto , con "incomplete" che significa "non include un'intera gamma di primitive logiche". Molto spesso si tratta di un sistema parziale che consente alcune operazioni di crittografia e decrittografia E (), D (), più alcune operazioni complicate ⊕ tali che

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

o simili.

Quindi vediamo come questo risolve il problema per alcuni giochi. Si consideri un gioco di tipo "luci spente" in cui si preme sugli esagoni N di una griglia esagonale e ognuno alterna sia il suo stato che gli stati di quelli intorno ad esso. Questa è un'algebra commutativa su quelle "presse" e quindi non ci sarà più di N presse totali in una data soluzione, più ogni esagono dipende solo dallo stato iniziale più le presse del proprio esagono più i 6 esagoni attorno ad esso.

Poiché il nostro schema di crittografia omomorfico consente solo +, non XOR, diamo a ciascun esagono un contatore a 3 bit per il numero di volte in cui è stato capovolto. (Il software client si ridurrà automaticamente ogni doppia pressione di un esagono ad una sola pressione.) Le azioni di inversione effettive sono quindi come i vettori di bit,

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

In altre parole hanno 1s in ciascuno di questi campi a 3 bit che si capovolge, più un 1 in un contatore a 16 bit.

Cifriamo tutti questi elementi con uno schema di crittografia omomorfico, inviamo ognuno di essi al client e il client ci restituisce un valore crittografato calcolato da questi valori crittografati che abbiamo inviato indietro. Quindi decifriamo questo e AND il valore decrittografato con il bitstring,

001 001 001 001 ... 001 11111111 00000000

e confronta con lo stato di gioco iniziale contiguo a 0 per questi 8 bit di contatore.

Se ci inviano un valore casuale, la loro possibilità di accettarlo è 2 - (N + 8) e quindi il loro unico modo utile per superare i test è usare i valori che abbiamo dato loro in alcune combinazioni consentite. Hanno accesso ad alcune mosse che non le stiamo permettendo direttamente a causa di overflow interi, ma possiamo sempre rendere i campi più larghi di 3 bit per renderli più costosi per il contatore a destra. Ma non abbiamo mai trasmesso le loro singole pressioni dei tasti, tanto meno ripetiamo la cronologia: abbiamo accettato un vettore che diceva "ecco come ho capovolto la griglia", che è la "cosa super insicura" di cui tutti ti stanno mettendo in guardia, ma noi ha fatto in modo che non possano fare le cose di cui siamo preoccupati senza accesso a una chiave segreta.

Invece si vede questo genere di cose nel voto crittografico dove si vuole avere la certezza che una macchina per il voto non dà spontaneamente 1000 voti ad Alice.

    
risposta data 15.01.2017 - 19:15
fonte
4

Tutto sul lato client può essere falsificato. Quindi la risposta è no.

EDIT Ho rimosso il meccanismo di sicurezza che ho scritto qui perché assicura solo sessioni legitime ... ma i punteggi falsificati possono essere inviati attraverso sessioni legitime. Grazie a @Luke Park

    
risposta data 15.01.2017 - 11:04
fonte
0

La mia raccomandazione è più una tecnica per l'offuscamento e potrebbe essere un ostacolo frustrante per molti utenti. Tuttavia, gli utenti avanzati o determinati potrebbero comunque analizzare il codice sorgente per riprodurre i risultati.

Utilizza uno strumento come Hashids per creare un hash del punteggio, e invia questo nella richiesta del tuo server insieme al punteggio del testo in chiaro. Il valore stringa dell'id utente potrebbe essere il sale utilizzato per codificare un hashid dello spartito, rendendo l'hash inutile se condiviso. Sul lato server è possibile decodificare questo hash e confrontare il risultato con il punteggio del testo in chiaro inviato per assicurarsi che corrisponda come previsto.

    
risposta data 18.01.2017 - 17:09
fonte

Leggi altre domande sui tag