Fråga:
Skicka ett högt poäng på klientsidan till en server säkert
StationaryTraveller
2017-01-15 15:45:41 UTC
view on stackexchange narkive permalink

Jag skapar en webbapplikation som innehåller ett enkelt javascript-spel. När spelaren är klar med spelet spelas poängen till servern och sparas.

Efter en viss period får spelaren med bästa poäng ett pris.

Finns det en sätt att skicka poängen säkert och förhindra att klienten skickar "falska" poäng?

För närvarande använder vi:

  • Https.
  • Servern slumpmässigt token före varje spel och skickas efter att spelet är avslutat vid sidan av poängen.
Det finns inget idiotsäkert sätt att lösa detta problem.Det enda sättet är att hålla reda på varje enskild poäng på servern.
TLS har inget att göra här, och du kan inte säkerställa något på klientsidan om det * försöker * vara skadligt.Du bör läsa ett [svar om ditt faktiska problem] (http://security.stackexchange.com/a/147047/91111).
Det finns en liknande fråga här, det översta svaret har en massa bra förslag.https://stackoverflow.com/questions/73947/what-is-the-best-way-to-stop-people-hacking-the-php-based-highscore-table-of-a-f
Förresten, du ställer den här frågan * alldeles för sent.Om det krävdes borde denna typ av säkerhet ha byggts in från början och inte ympas senare.
OTOH, om incitamentet att knäcka ditt spel (och så falska höga poäng) är mindre än svårigheten att knäcka det, kan ditt spel klara sig helt enkelt för att det inte finns tillräckligt intresse för att fejka poängen.
Sex svar:
grc
2017-01-15 16:54:50 UTC
view on stackexchange narkive permalink

Servern kan inte helt lita på data som den tar emot från klienten, så det är svårt att validera höga poäng.

Här är några alternativ:

  1. Fördunkla klientsidans kod och trafik till servern. Detta är det enklaste alternativet - det kommer fortfarande att vara möjligt att fuska, men förmodligen kommer det inte att vara värt någons tid.

  2. Skicka en fullständig eller delvis återuppspelning av spelet till servern för validering. Spelarens drag kan köras på servern för att bestämma den legitima poängen. Detta fungerar för vissa spel och inte för andra.

  3. Flytta spellogiken och valideringen till servern. Klienten vidarebefordrar helt enkelt varje drag till servern, där den valideras och spelets tillstånd uppdateras.

Det handlar om hur ditt spel fungerar, hur sannolikt det är att människor kommer att fuska, och hur mycket du bryr dig om de gör det.

# 3 är det enda rätta sättet att göra detta
@theonlygusti Kanske missförstår jag poängen men du behöver inte flytta spellogiken - du behöver bara replikera den på servern.Om allt du skickar är alla spelarens ingångar kan servern spela upp dem igen och verifiera poängen.Då behöver du bara bry dig om "TASbot" -spelare :).För ett exempel på ett spel som gör det bra - DROD.Eftersom det är ett logiskt spel är det också motståndskraftigt mot verktygsassisterade genomspelningar.Det enda ofixbara problemet är snipning, där någon tittar på andra spelares demo och letar efter optimeringspunkter.
@Maurycy Jag sa bara att det enda sättet att vara säker på att en highscore är giltig är att hantera spelet på servern.Att flytta / replikera spelar ingen roll
@theonlygusti Jag menar poängen säger "flytta spellogiken" och jag kände att det måste tas bort att du bara behöver replikera den.Jag borde antagligen ha taggat dig i kommentaren eftersom jag verkligen tänkte svara på svaret som helhet, inte din kommentar :)
@theonlygusti: För många typer av spel är 2 lika bra som 3.
@theonlygusti Correction, # 3 är det enda * idiotsäkra * sättet att göra detta (men det är faktiskt inte sant eftersom det inte är idiotsäkert!).Det är bara det mest idiotsäkra och svåraste av alternativen.
@theonlygusti, för deterministiska spel (tänk: Tetris), nummer 2 kommer att fungera så länge du inte har något emot att ge AI-poäng med höga poäng.
@Mark # 2 har också nackdelen att en klient kan optimera baserat på framtida kunskap.T.ex.i Tetris om du känner till alla bitar du kommer att få, kan du hitta en bättre strategi än om du bara får en bit, placera den någonstans och få nästa.
# 1 är värdelöst med ett javascript-spel, eftersom det är _mycket_ lättare att återskapa läsbar kod än med något annat språk.
Philipp
2017-01-15 16:54:58 UTC
view on stackexchange narkive permalink

Om din angripare var en man-i-mitten-angripare på nätverkslagret, skulle https vara tillräckligt. Men tyvärr är din angripare klienten, så det här är ganska meningslöst.

Regel nummer ett av fusksäkra spel: Lita aldrig på klienten! Klienten är i fiendens händer.

Javascript-spel körs i användarens webbläsare. Som du som webbutvecklare säkert vet kommer varje webbläsare idag med en inbyggd felsökare som kan visa och ändra alla variabler medan ett program körs. Användaren kan helt enkelt använda felsökaren för att ändra sin poäng innan den skickas. Det finns inget du kan göra för att förhindra det. Med webbläsarbaserade spel kan du inte ens slå ett tredjeparts-anti-fuskverktyg på dem (som är av tvivelaktigt värde och i alla fall etiskt ifrågasatta).

Den enda motåtgärden är att genomföra alla spelmekaniker som är värda att manipulera på servern. Klienten ska inte göra annat än att vidarebefordra användarens kommandon till servern och visualisera spelet baserat på serverns meddelanden. Den faktiska spelningen ska ske på servern där den är utom räckhåll för fuskarna.

Ja, det betyder att du måste omforma ditt spelets programvaruarkitektur från grunden. Det betyder också att du måste lägga till lite förutsägelse och interpolationskod för att göra nätverksfördröjningen mindre synlig. Och det betyder också att du kommer att behöva mycket bättre serverhårdvara och en bättre internetanslutning för din server (s). Men när du vill ha ett fuskfritt onlinespel är det enda alternativet.

Det finns det vanliga ** förtroendet, men verifiera ** svaret - se alternativ 2 i grcs svar.
@MSalters Är inte ** förtroende, men verifierar ** en oxymoron?Du litar inte på klienten, varför du verifierar svaret.Om du litar på klienten, varför behöver du verifiera den?
@Tom "Lita på men verifiera" är en vanlig fras som kommer från ett ryskt ordspråk (se [Wikipedia] (https://en.wikipedia.org/wiki/Trust,_but_verify)).Och ja, det är oxymoronic, men du kan också läsa det som i samma åder som "oskyldig om inte bevisat skyldig".Eller, apropos, när Wikipedia antar att användare agerar i god tro vid redigering (det är bara en wiki eftersom det inte är låst), men kräver fortfarande att de citerar referenser.
Lie Ryan
2017-01-15 22:29:01 UTC
view on stackexchange narkive permalink

För att uppnå säker spelhög poäng behöver du ett " bevis på arbete", eller snarare, mer lämpligt kallat proof of play.

Ett bevis på arbete / spela är alla data som är svåra att beräkna innan du avslutar spelet, men lätt att beräkna när du är klar med spelet och är lätt att verifieras av servern. Till exempel, för ett Sudoku-spel är ett bevis på arbete lösningen på pusslet.

Tyvärr finns det inget generiskt sätt att integrera lämpligt proof of play-system i många spel. Det är inte alltid möjligt att integrera ett bevis på spel utan att justera eller omarbeta spelet, eller begränsa räckvidden för ledartavlan till bara element där du kan inkludera tillräckligt säkert bevis på spel.

Spelbevis på en spelet börjar med att servern utfärdar fröet för spelets RNG. Klienten måste då hitta ett bevis på spelet som matchar det frö som spelaren hade utfärdat. I många spel kan ett bevis på spel skapas genom att skicka spelets lösning till servern med hög poängsändning, i andra kan det vara nödvändigt att spela in hela spelsessionen i olika detaljeringsnivåer beroende på spelet och beviset på spel du använder.

Ett bevis på spel måste vara omspelningsbeständigt (en spelare borde inte kunna använda en annan spelares färdiga spel för att göra sitt eget bevis på spel lättare att beräkna). Detta begränsar bevis på spel till spel där det finns en slumpmässighet att spelare inte bara kan återanvända en annan spelares bevis på spel, men det kan inte heller ha för mycket icke-deterministiskt beteende till den punkt där det blir omöjligt att verifiera spelet. spel är också begränsat. I ett Sudoku-spel är det till exempel inte möjligt att bevisa hur lång tid spelaren tar för att lösa pusslet. Bevis på spel kan inte alltid skilja mellan spel som spelaren spelar och spelaren som har skrivit ett manus som spelade spelet för dem.

Ett tillvägagångssätt för att förhindra "plagiering" av lösningar skulle vara att ha spelarens namn specificerat innan spelet startar, hash slumpmässigt nummer frö enligt det namnet.och låt spelet rapportera det oskadade utsäde tillsammans med namnet och lösningen.
Det är lätt att spåra tiden eftersom vi ** har en serversida här.Det är mängden mellan genereringen av pusslet och inlämnandet av resultatet.
CR Drost
2017-01-16 00:15:32 UTC
view on stackexchange narkive permalink

Jag ville bara nämna att det finns en slags lösning på detta problem men det är sannolikt inte tillgängligt för dig; lösningen kallas "homomorf kryptering" och det gör det möjligt för en klient att utföra en känd beräkning utan att veta exakt vilka värden de beräknar med, och en server som därför kan kontrollera strukturen för det beräknade värdet för att bevisa att klienten inte bara skicka tillbaka en slumpmässig sträng men byggde den faktiskt ut ur de angivna värdena.

Problemet är att det antingen är långsamt eller ofullständigt , med "ofullständigt" vilket betyder "inte innehåller ett komplett utbud av logiska primitiver." Mycket ofta är det ett partiellt system som tillåter vissa krypterings- och dekrypteringsoperationer E (), D (), plus en del komplicerad operation operation så att

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

eller liknande.

Så låt oss se hur detta löser problemet för vissa spel. Tänk på ett spel med "ljus ut" -typ där du trycker på N hexarna i ett sexkantigt rutnät och var och en växlar både dess tillstånd och tillstånden för dem runt det. Detta är en kommutativ algebra för dessa "pressar" och därför kommer det inte att finnas mer än N pressar totalt i en given lösning, plus varje hex beror bara på initialtillståndet plus pressarna på sin egen hex plus de 6 hexorna runt den.

Eftersom vårt homomorfa krypteringsschema endast tillåter +, inte XOR, ger vi varje hex en 3-bitars räknare för det antal gånger den har vänt. (Klientprogramvaran krymper automatiskt varje dubbeltryck av en hex till bara ett tryck.) De faktiska vändningsåtgärderna är därför bitvektorer som ser ut,

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

Med andra ord har de 1s i vart och ett av dessa 3-bitarsfält som den vänder, plus en 1 i någon 16-bitars räknare.

Vi krypterar alla dessa med ett homomorfiskt krypteringsschema, skickar var och en av dem till klienten och klienten skickar tillbaka oss ett krypterat värde beräknat från dessa krypterade värden som vi skickade tillbaka. Vi dekrypterar sedan detta och OCH det dekrypterade värdet med bitsträngen,

  001 001 001 001 ... 001 11111111 00000000  

och jämför med det ursprungliga spelet -stat tillsammans med 0 för de 8 motbitarna.

Om de skickar oss ett slumpmässigt värde är deras chans att vi accepterar det 2 - (N + 8) och därför deras enda användbara sättet att klara testerna är att använda de värden som vi gav dem i någon tillåten kombination. De har tillgång till vissa drag som vi inte tillåter dem direkt på grund av heltalsspill, men vi kan alltid göra fälten bredare än 3 bitar för att göra dessa dyrare för räknaren till höger. Men vi överfördes aldrig deras enskilda knapptryckningar, mycket mindre omspelning av historien: vi accepterade en vektor som säger "här är hur jag vred på nätet", vilket är den "superosäkra sak" som alla varnar dig för, men vi gjorde det på ett sådant sätt att de inte kan göra de saker vi är oroliga för utan tillgång till en hemlig nyckel. ger inte spontant 1000 röster till Alice.

Jag förstår inte varför krypteringen är till hjälp här.Det enda sättet vi ser till att klienten faktiskt löser pusslet är att inkludera det "bevis på arbete" han gjorde.Vilken skillnad gör det om beviset på arbetet inte krypterades?
@AgnishomChattopadhyay Kan du tänka dig någon situation där beviset på arbete för någon lösning S är väsentligt längre än S själv?Tack vare homomorf kryptering behöver du i princip inte.
OscarAkaElvis
2017-01-15 16:04:08 UTC
view on stackexchange narkive permalink

Allt på klientsidan kan falska. Så svaret är nej.

REDIGERA Jag tog bort säkerhetsmekanismen jag skrev här eftersom den bara försäkrar legitima sessioner ... men falska poäng kan skickas genom legitima sessioner. Tack @Luke Park

Jag fick inte ditt andra stycke.Låt oss säga att jag behåller den 'slumpmässiga' token på serversidan.Hur kan jag validera det när klienten skickar poäng? Och i tredje stycket, vad menar du med att skicka inledande slumpmässigt token säkert?
Skicka det på serversidan betyder att om du till exempel använder php måste du skicka det med php på backend, inte av js.Jag antar att klienterna inte kan sniffa någonting och om du använder https som du sa räcker det.För att validera det måste du ta emot och lagra initialt token (i databas i session eller var som helst) på poängservern och sedan, efter att ha mottagit klientens token (som kan förfalskas), måste du jämföra med initial token skickad (som är säker)ingen möjlighet att lura det.
Vad som helst på klientsidan kan förfalskas, det sa du själv.Resten av ditt svar är därför onödigt.
@Luke Park, frågade han 'Finns det ett sätt att skicka poängen säkert och förhindra att klienten skickar' falska 'höga poäng? Så jag försöker förklara hela processen
Det finns ingen hel process.Du kan inte förhindra det.Allt som den legitima klienten gör kan förfalskas av en olaglig klient.
Du har fel.Poängen är att servern kan skapa en första token för spelet som skickas i backend till poängservern.Den här token är SÄKER.Sedan, efter spel kan klienttoken falskas, ok, men säkerhetsmekanismen är att token som skickas av klienten måste matcha den säkra token som skickas först när spelet skapades.
Men klienten är fortfarande den som skickar poängen till servern, eller hur?Med symbolen?
Låt oss [fortsätta denna diskussion i chatt] (http://chat.stackexchange.com/rooms/51820/discussion-between-oscarakaelvis-and-luke-park).
Efter ett tag tänker jag djupare på det, jag tror att du har rätt Luke Park, förlåt.Jag redigerade mitt svar.
Ben Harrison
2017-01-18 22:09:42 UTC
view on stackexchange narkive permalink

Min rekommendation är mer en teknik för förmörkelse och kan möjligen vara ett frustrerande hinder för många användare. Dock kan avancerade eller bestämda användare fortfarande analysera din källkod för att återge resultaten.

Använd ett verktyg som Hashids för att skapa en hash av poängen och skicka detta i din serverförfrågan tillsammans med klartextpoäng. Strängvärdet för användar-id kan vara det salt som används för att koda en hashid av poängen, vilket gör hash värdelös om den delas. På serversidan kan du avkoda denna hash och jämföra resultatet med klartextpoängen som skickades för att se till att de matchar som förväntat.

Jag ville notera att hashids bara är ett verktyg som kan användas.En begränsning med detta speciella bibliotek är att det inte stöder negativa siffror (förutsatt att ditt spel kanske behöver det).
Det är bara lite bättre än att skicka en vanlig text eftersom användaren känner till sitt ID och kan avkoda det precis som servern gör.


Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...