C'est un problème classique des jeux et concours sur Internet. Votre code Flash travaille avec les utilisateurs pour décider du score d'un jeu. Mais les utilisateurs ne sont pas dignes de confiance et le code Flash s'exécute sur l'ordinateur de l'utilisateur. Vous êtes SOL. Il n'y a rien que vous puissiez faire pour empêcher un attaquant de falsifier des scores élevés :
-
Flash est encore plus facile à désosser que vous ne le pensez, car les bytecodes sont bien documentés et décrivent un langage de haut niveau (Actionscript) --- lorsque vous publiez un jeu Flash, vous publiez votre code source, que vous le sachiez ou non.
-
Les attaquants contrôlent la mémoire d'exécution de l'interpréteur Flash, de sorte que toute personne sachant utiliser un débogueur programmable peut modifier n'importe quelle variable (y compris le score actuel) à tout moment, ou modifier le programme lui-même.
L'attaque la plus simple contre votre système consiste à faire passer le trafic HTTP du jeu par un proxy, à récupérer la sauvegarde du meilleur score et à la rejouer avec un meilleur score.
Vous pouvez essayer de bloquer cette attaque en liant chaque sauvegarde de score élevé à une seule instance du jeu, par exemple en envoyant un jeton crypté au client au démarrage du jeu, qui pourrait ressembler à ceci :
hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))
(Vous pourriez également utiliser un cookie de session pour le même effet).
Le code du jeu renvoie ce jeton au serveur avec la sauvegarde du meilleur score. Mais un attaquant peut toujours relancer le jeu, obtenir un jeton, puis coller immédiatement ce jeton dans une nouvelle sauvegarde de score élevé.
Ensuite, vous fournissez non seulement un jeton ou un cookie de session, mais aussi une clé de session chiffrant les scores élevés. Il s'agit d'une clé AES de 128 bits, elle-même cryptée avec une clé codée en dur dans le jeu Flash :
hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))
Avant que le jeu n'affiche le meilleur score, il décrypte la clé de session de cryptage du meilleur score, ce qu'il peut faire car vous avez codé en dur la clé de décryptage de la session de cryptage du meilleur score dans le binaire Flash. Vous cryptez le score élevé avec cette clé décryptée, ainsi que le hachage SHA1 du score élevé :
hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))
Le code PHP sur le serveur vérifie le jeton pour s'assurer que la requête provient d'une instance de jeu valide, puis décrypte le score élevé crypté, en vérifiant que le score élevé correspond au SHA1 du score élevé (si vous sautez cette étape, le décryptage produira simplement des scores élevés aléatoires, probablement très élevés).
Ainsi, l'attaquant décompile votre code Flash et trouve rapidement le code AES, qui se distingue comme un pouce endolori, bien que même si ce n'était pas le cas, il serait retrouvé en 15 minutes avec une recherche en mémoire et un traceur ("Je sais que mon score pour ce jeu est de 666, alors trouvons 666 en mémoire, puis attrapons toute opération qui touche cette valeur --- oh regardez, le code de cryptage du score le plus élevé !) Avec la clé de session, l'attaquant n'a même pas besoin d'exécuter le code Flash ; il saisit un jeton de lancement de jeu et une clé de session et peut renvoyer un score élevé arbitraire.
Vous en êtes maintenant au point où la plupart des développeurs abandonnent --- après quelques mois d'efforts pour contrer les attaquants :
-
Brouillage des clés AES avec des opérations XOR
-
Remplacement des tableaux d'octets de clé par des fonctions qui calculent la clé
-
Disperser de fausses clés de chiffrement et des affichages de scores élevés à travers le binaire.
Tout cela n'est qu'une perte de temps. Il va sans dire que le SSL ne vous aidera pas non plus ; le SSL ne peut pas vous protéger si l'un des deux points d'extrémité du SSL est mauvais.
Voici quelques éléments qui peuvent réellement réduire la fraude au score élevé :
-
Exigez une connexion pour jouer au jeu, faites en sorte que la connexion produise un cookie de session, et n'autorisez pas plusieurs lancements de jeu en cours sur la même session, ou plusieurs sessions simultanées pour le même utilisateur.
-
Rejetez les scores élevés des sessions de jeu dont la durée est inférieure à celle des parties réelles les plus courtes jamais jouées (pour une approche plus sophistiquée, essayez de "mettre en quarantaine" les scores élevés des sessions de jeu dont la durée est inférieure de 2 écarts types à la durée moyenne des parties). Assurez-vous que vous suivez la durée des parties sur le serveur.
-
Rejetez ou mettez en quarantaine les scores élevés des connexions qui n'ont joué au jeu qu'une ou deux fois, de sorte que les attaquants doivent produire une "trace écrite" d'un jeu d'apparence raisonnable pour chaque connexion qu'ils créent.
-
Les scores "en cœur" pendant le jeu, de sorte que votre serveur voit la croissance du score au cours de la durée d'une partie. Rejetez les scores élevés qui ne suivent pas des courbes de score raisonnables (par exemple, un saut de 0 à 999999).
-
des "instantanés" de l'état du jeu pendant la partie (par exemple, la quantité de munitions, la position dans le niveau, etc.), que vous pouvez ensuite rapprocher des scores intermédiaires enregistrés. ), que vous pouvez ensuite rapprocher des scores intermédiaires enregistrés. Il n'est même pas nécessaire de disposer d'un moyen de détecter des anomalies dans ces données pour commencer ; il suffit de les collecter, puis de revenir en arrière et de les analyser si les choses semblent suspectes.
-
Désactivez le compte de tout utilisateur qui échoue à l'un de vos contrôles de sécurité (par exemple, en soumettant un score élevé crypté qui échoue à la validation).
N'oubliez pas cependant que vous ne faites que décourager la fraude aux scores élevés. Il y a rien que vous pouvez faire pour prévenir si. S'il y a de l'argent en jeu dans votre jeu, quelqu'un va déjouer tous les systèmes que vous mettez en place. L'objectif n'est pas de arrêter cette attaque ; il s'agit de rendre l'attaque plus coûteuse que le simple fait de devenir très bon au jeu et de le battre.