ajax - Ensuring retrieved JSON is validated from the correct server for Javascript games -


i'm trying establish technique verify data server, simple javascript game. understand there many issues trying protect javascript application as, definition, of code available client-side.

for example, it's game, if:

  var playerscore = 100 

to stop people editing javascript , running such...

  var playerscore = 10000000 

...i validate on server. however, (to me) seems add trivial step hack game. couldn't hacker\tweaker change destination of ajax request own local files?

i thought maybe trying compare on-the-fly key\encryption of common value, e.g. date, between client , server, again, encryption methods visible trivial avoid.

i know broad subject, there best practices can recommend? i've seen post ( prevent javascript games tweaking/hacking ) , helpful regards preventing tampering, i'm not sure how verify correct server-side validation taking place.

as always, many in advance.

to answer questions directly:

q - "couldn't hacker\tweaker change destination of ajax request own local files?"

a - if script not obfuscated yes can change ajax request destination use own game server. obfuscated scripts can unpacked change request destination of hackers game implications of them doing so? have own version of game doing own thing, talking own server... hardly real problem unless there secrets unlock in client game, having own server might make these secrets marginally easier uncover reading client source.

the game server could, protect game secrets, however, drop these secrets script payloads during game... in case need read on.

q - know broad subject, there best practices can recommend? ... i'm not sure how verify correct server-side validation taking place.

a - preventing forgery of game state , stats on game server, which, don't believe asking... believe asking how prevent game client having incorrect game state, impossible, client code leaves server can tampered , measures prevent contained in client code , nature, reversible , therefore circumventable...

countermeasures prevent hacking game server stats

assuming client authority on current game score , server not running authoritative version of game session , receiving user input updates client (in case, user input needs sanitized, introduces complexity in state needs synchronized server client , sensitive latency issues).

it seems problem in general has no perfect solution mitigates hacking, let alone javascript game, example, in flash compiled problem still apparent: what best way stop people hacking php-based highscore table of flash game, @ executable level on system: how can protect .net assemblies decompilation?.

javascript not compiled , sent plain text doesn't have these barriers (that circumventable) hacking.

i've compiled approach mitigating problem, various resources linked , google searching, game:

var score = 0; function increasescore() {     score ++;     sendscore(); } function sendscore() {     // ajax } function run() {     settimeout(function() {         increasescore();     }, 1000); } run(); 
  1. closure: using closure around running code prevent functions , variables being called through browser console. doesn't prevent breakpoints or modifying script remove closure.

    (function() {     var score = 0;     function increasescore() {         score ++;         sendscore();     }     function sendscore() {         // ajax     }     function run() {         settimeout(function() {             increasescore();         }, 1000);     }     run(); }) (); 
  2. obfuscation: can use dean edwards packer, or minify code using closure compiler. minification wont prevent watching , changing variables through browser console both prevent source being human readable, required hacker find sensible breakpoints watch.

    the dean edwards packer turns script string eval-ed makes impossible add breakpoints original script. is, however, possible unpack script , hacker use script instead add breakpoints.

    eval(function(p,a,c,k,e,r){e=string;if(!''.replace(/^/,string)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new regexp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(1(){6 2=0;1 3(){2++;4()}1 4(){}1 5(){7(1(){3()},8)}5()})();',9,9,'|function|a|increasescore|sendscore|run|var|settimeout|1000'.split('|'),0,{})) 
  3. encryption: client encrypts scores before sending, wont prevent modifying scores through browser debugger if hacker has access encryption function, prevent simple forgery of scores in server request.

  4. game instance token: server includes unique token in request sent server on start of game. prevents simple modification of script (as in unpacking or removing closure) instance token have been used original script, invalidating it.

    the determined hacker need remove code sends token around this, need ensure scores being sent logically pick original game instance (see step 6. , made more complex because of step 5.).

    (function() {        var score = 0;     var token = "abcdef123456789"; // inserted server side code      function increasescore() {         score ++;         sendscore();     }     function sendscore() {         var encrypted = encryptscore();         // ajax send encrypted     }     function encryptscore() {         // uses encryption lib     }     function sendtoken() {         // ajax send token     }     function run() {         sendtoken();         settimeout(function() {             increasescore();         }, 1000);     }     run(); }) (); 
  5. scoring token: server sends token next score encrypted with. reduces size of attack window. if hacker has found code encrypt score send still need correct token current score update.

    (function() {        var score = 0;     // yes easy add items onto queue     // closure , packing prevent breakpoints, plus     // session token required prevent     var queue = [];     var token = "abcdef123456789"; // inserted server side code      var sending = false;     function increasescore() {         score ++;         queue.push(score);         if(!sending)             sendscores();     }     // scores need sent sequentially, last     // score sent response have next scores token     function sendscores() {         sending = true;         var encrypted = encryptscore(queue.shift(), token);         // ajax send encrypted, send next score when          // response received, if there next score          // in queue, otherwise stop sending          // (sending = false)     }     function encryptscore(score, token) {         // uses encryption lib     }     function sendtoken(callback) {         // ajax send token, sets new token value server response     }     function run() {         sendtoken(function() {             settimeout(function() {                 increasescore();             }, 1000);         });     }     run(); }) (); 
  6. server side sense checking: server checks if user's score has increased more deemed possible, (or decreased in case of reusing instance token above), step in sequential score updates great, illogical or score has increased rapidly within given period.

  7. blacklisting: quarantine users , sessions show cheating behaviour not apparent hacker have been found out , scores silently removed valid score pool.

  8. greylisting: flagging users or game sessions appear close perfect scoring scenario manual investigation decide whether blacklist.

in general create audit data possible try , monitor situation, manually intervene necessary , add more preventative measures problems reoccur in live situation.

also, because there no perfect solution problem making difficult needed not worth time required hack it. there persistent hackers challenge, keep in perspective: if hacker did try hack scores current countermeasures in place result , worth time circumvent?

at guess commercial game producers use tricks in book, depend on budget vs risk.


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

javascript - jQuery .height() return 0 when visible but non-0 when hidden -