Adobe’s proprietary Flash format has become a significant part of the Internet as it is today. While its importance in Web applications is slowly decreasing due to Web 2.0 technologies and HTML5, it is still a major player in the browser game and application sector. The majority of these games and applications are for entertainment only and offer you nothing but a nice rank in the high score. On rare occasions, however, there are Flash games in which you can actually win something valuable such as concert tickets or even money. And of course there are applications that let you stream, but not download content from a website.

So what’s the problem with that, you think? The problem is that almost all Flash applications can be hacked very easily and most developers are not aware of that.

As a reminder of how vulnerable Flash applications are, this post aims to raise awareness for these issues. In a case study, it shows how a Flash-based game and its server side high score can be tricked within a few minutes using free tools only.

Contents

Disclaimer

This post is meant to raise awareness for the vulnerabilities of Flash-based applications. It is not a hacking tutorial or how-to. For that reason, I will not describe all steps in great detail, but only sketch the basic steps.

1. Introduction

1.1. The problem with Flash applications

Flash applications are similar to normal Windows/Linux executables: Like normal programs, their source code is compiled to a binary format and later executed on the client machine. The major difference to .exe or Linux binaries is that decompiling is a lot easier: while a C or C++ compiler translates the source code into machine code, i.e. CPU instructions, SWF files contain the ActionScript code in plain text. That is with the right tools, extracting the complete code is a no-brainer!

Combining this with the fact that sniffing into the client-server communication is also not the most difficult task, one can easily simulate the Flash client with own code snippets and scripts, and thereby send forged requests to the server.

1.2. Checksums as a solution?

Most application developers at least know that the client-server communication can be sniffed into. As an attempt to make it more difficult for people to send forged requests to the server, applications mostly use a message authentication code (MAC) or some other checksum-based mechanism. So instead of sending a plain text update query to the server (1), the application creates a hash by concatenating the user input with (to the user unknown) other data (2):

(1) Without checksum mechanism (2) With checksum mechanism POST /write-highscore.php HTTP/1.1

Host: www.example.com

User-Agent: Mozilla/5.0 …

…

name=Phil&score=40 POST /write-highscore.php HTTP/1.1

Host: www.example.com

User-Agent: Mozilla/5.0 …

…

name=Phil&score=40& check=283647a…

This mechanism is completely based on the fact that the user does not know how the checksum is created. While this approach is very effective in regular applications, it completely fails in Flash programs: disassembling a Windows or Linux binary is very difficult and requires know how in assembler. Decompiling SWF files, however, is fairly easy and can be done in under a minute. That is retrieving the code that generates the checksum is only a matter of seconds.

The following steps present a generic approach on how any Flash application can be exploited like described above.

Required Tools:

Firebug (was at: https://addons.mozilla.org/en-us/firefox/addon/firebug/, site now defunct, July 2019, use F12 tools instead): Firefox plugin for basic communication sniffing

Sothink Flash Decompiler: required to extract ActionScript code (trial version is sufficient)

Wireshark: required for detailed communication sniffing (byte-for-byte)

Generic Approach:

Enable Firebug and start sniffing with Wireshark. Go to the target web site and play the game or use the application. Look at the communication of the Flash application with the server. If there are any parts of the requests that cannot be recreated without the source code, e.g. checksums, download the important SWF files and decompile them. Analyze the ActionScript code and find the part which creates the checksum. Make a script that generates the same request with arbitrary input data, e.g. any score or name. For this script, the checksum algorithm from the ActionScript code can be used (or recreated).

2. Case study: a car parking game (with high score)

Our local newspaper Mannheimer Morgen recently hosted a competition in which users had to park a (virtual) car into different parking spots without damaging the car and with minimal fuel usage. Prizes were a safety training and concert tickets. While in this case the score of the participants did not decide who won (winners were drawn by lot), the winner in other competitions might be the one with the best score. Please note that I did not take part in this competition and I did under no circumstances try to win the prizes.

Parking Game: The target application in this case is a game called “Parking”.

2.1. Capture the client-server communication

Following the instructions from above, the first step is to capture the communication between the Flash client and the server. In this case, we are particularly interested in how to add our name with an arbitrary score to the high score list.

Firebug:

Using Firebug, we can see three interesting requests:

savescore.swf is the part of the client that is responsible for sending the score to the server.

serverdate-read.php is called by savescore.swf for no obvious reason – very suspicious. We will later see that the result is used in the checksum generation.

highscore-write.php is also called by savescore.swf and actually writes the user’s score to the database on the server.

Firebug identifies the interesting files and requests.

In this case, three requests are relevant for the high score forgery.

What is particularly important is the two parameters __ctrl and controlvalue. Both are obviously generated by some checksum function in the savescore.swf-file. So the next step is to decompile the SWF file and look for the checksum-generating function.

Wireshark:

If we additionally enable Wireshark, we can get a plain text (or hex) representation of the HTTP request-response cycle. That is particularly important if one wants to forge a request in a way that it cannot be detected by the server.

2.2. Decompile the SWF file and find the checksum algorithm

Using the SWF Decompiler software (trial version is sufficient), the savescore.swf can be examined very closely. Most of the applications are not very complex and the relevant code pieces are found very easily.

When analyzing savescore.swf, the two parts in which the checksums are created are found at different positions in the file. The __ctrl parameter is generated by taking a MD5 hash over the two concatenated values of score and email. The controlvalue parameter is created in a similar fashion and involves the previously queried serverdate.

The __ctrl parameter is a hash value over two of the variable input parameters.

The controlvalue parameter is created similarly.

2.3. Write a script

Once it is clear how the checksums are generated, the puzzle is solved. The only thing left is to write a script that allows entering arbitrary input values, and using the previously determined checksum-mechanisms to generate a MAC.

Here is a short excerpt of how this could look like (using PHP):

$score = "999.999"; $email = "nobody@example.com"; $data = array( "__ctrl" => md5($score.$email), ... "score" => $score, "controlvalue" => md5(...), ... ); foreach($data as $k=>$v) $data_enc[] = urlencode($k)."=".urlencode($v); $req = "POST /parking/highscore-write.php HTTP/1.1rn" . "Host: www.morgenweb.dern" ... . join("&",$data_enc); $fp = fsockopen("www.morgenweb.de", 80); fwrite($fp, $req); while ($line = fgets($fp)) { } fclose($fp); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $score = "999.999" ; $email = "nobody@example.com" ; $data = array ( "__ctrl" =& gt ; md5 ( $score . $email ) , . . . "score" =& gt ; $score , "controlvalue" =& gt ; md5 ( . . . ) , . . . ) ; foreach ( $data as $k =& gt ; $v ) $data_enc [ ] = urlencode ( $k ) . "=" . urlencode ( $v ) ; $req = "POST /parking/highscore-write.php HTTP/1.1rn" . "Host: www.morgenweb.dern" . . . . join ( "&" , $data_enc ) ; $fp = fsockopen ( "www.morgenweb.de" , 80 ) ; fwrite ( $fp , $req ) ; while ( $line = fgets ( $fp ) ) { } fclose ( $fp ) ;

3. Conclusion

This blog post introduced a common way to outsmart Flash applications and games. It demonstrated that by sniffing into client-server communication and decompiling SWF files, many Flash applications can be misused. Using the example of a Flash game, the post showed that SWF cannot be compared to Windows/Linux binaries, but must rather be seen as JavaScript-like client code.

Even though this post only demonstrated this using a rather harmless game, more serious misuse is also possible. Flash-based music streaming sites such as Simfy (was at: simfy.com, site now defunct, July 2019), Spotify or Grooveshark (was at: grooveshark.com, site now defunct, July 2019) are affected as well. They all use a similar mechanism for their Flash-based music player. Using the approach presented above combined with tools like rtmpdump can potentially harm their services significantly.

Flash once was a great way for bringing a little dynamic in the Web 1.0, but is now outdated. With various JavaScript frameworks and HTML5 on the way, Flash is going to retire soon. Developers and companies must be aware of the flaws of Flash and adjust their services accordingly to make sure that they cannot be misused.























































































