Over the years I've become an uber-nerd when it comes to flash game development. Now I'm thinking about looking into using my skills for helping other game-developers out there.
I want to develop an API in AS3 which will allow the developer to do (as a start) the following:
Display a dialogue which lets the user log into their "account" (hosted on my site).
Send a score/value to the website and attribute it to the logged in user.
Unlock an achievement (achievements will be set up by the developer in the web interface - which is where they will also get a key of some type to use with their API.
Display high scores, other players profiles in-game, etc (show basically any stats in-game).
All easy enough to develop straight off the bat. However; where it becomes frustrating is security. I'm not expecting an indestructible solution that I'm fully aware isn't possible, but what would be the most defensive way to approach this?
Here are the issues that I can think up on the spot:
The big one - people stealing the API key via man-in-the-middle attack.
Highscore injection, false achievement unlocks.
Decompiling the SWF and stealing the API key.
Using the API key to create a dummy flash application and send random data like highscores.
Altering the API itself so you don't need to be logged in, etc.
One thought I've had was converting my API to a component so there's no access to the code (unless you decompile). The problem here is it's just not friendly to the developers, though it would allow me to create my own graphics for the UI (rather than coding many, many sprites).
Private/public keys won't work unless there is very good protection against decompiling.
I'm beginning to wonder if this idea is a dead end.
Any advice on securing this (or parts of it) would be great.
Look at this thread first if you haven't done so already: What is the best way to stop people hacking the PHP-based highscore table of a Flash game
Against man-in-the-middle HTTPS seems the only option. It may have its vulnerabilities, but it's way better than any home-made solution. The problem that you'll need actual certificate from authorized center, because ActiveX-based Flash plugin will not trust self-signed certificate.
Should not be possible without decompilation
SecureSWF with reasonably high settings (code execution path obfuscation and encrypted strings) should beat most decompilers. Sure, SWF can be examined with hex editor, but this will require very determined hacker.
Should not be possible without decompilation
API should be on server and any API function would require user context (loaded by HTTPS)
Also add encryption to flash shared objects\cookies. I had successfully altered some savegames using simple hex editor, because they were just objects in AMF format. Encryption will depend on SWF decompilation, but since we are using SecureSWF... Or move savegames on server.
client side is never secure enough, so i'd suggest to take all the logic to the server, reducing client to just UI.
If it's impossible due to network timeouts - send scores/achievements only with the log of pairs "user_action - game_state" and verify it on the server.
Related
I am trying to figure out a way to do an internet connectivity check for an AIR for iOS app. Previously, I was using (against my better judgement) a URLMonitor that checked Google once every 30 seconds. I did not like putting that load onto Google and neither did they; this morning, our network got flagged as a possible DDoS attacker simply from testing the app. So I had to disable this type of check and move on.
I have thought about using the NetworkInfo ANE from Adobe, but that presents its own issues in determining internet connectivity. The only way I can think of doing it is to check for interfaces "en0" and "pdpxx" (which correspond to WiFi and Cellular interfaces, respectively) and check their IPs to ensure they are not in the 192.168.x.x, 10.10.x.x, or 127.0.x.x ranges. However, I am not entirely sure those are the only static router/localhost IPs out there and there is always the possibility that the network interface names will change in the future, which would render this monitor useless. There is also the issue of IPv6 possibly throwing a wrench into this method as well.
Is there another way to check if the user is connected to the internet? I've searched multiple times and it seems that these are the only two ways to check. If that is the case, what is the best way to check?
I'm surprised that you got flagged as a DDoS attacker, are you sure that's what happened?
In any case, if your not happy with putting the load onto someone else's server, then make your own server, just a basic setup that you use with the URLMonitor. You don't have to use google's url with the URLMonitor, you can pass it another URLRequest, which could point to your own server.
monitor = new URLMonitor(new URLRequest("http://www.you-own-server.com"));
This might also be useful if you decide that you want to pass more data between the app and the server. It's your server, so can do what you want with it.
I don't think there's any other way to check if the user is connected to the internet. To be honest, I don't see why there would be. Checking for the users interfaces/wan0 etc... probably would be possible, but you'd need another program, maybe a simple python or c++ program, that Air could use to check these things, but that sounds like the long way round.
Question
How do I secure an API by only allowing trusted domains?
Details
I am building a REST API. I need a way to distribute API Keys but only allow them to work from the domain they are registered with.
The main issue is my API Key needs to be embedded in a Flash File which can easily be decompiled to steal the API Key. If Flash makes this impossible I can use Javascript instead.
I have heard a lot of people say use $_SERVER['HTTP_REFERER']. But that is easily spoofed.
How do I build an API that makes sure a request is coming from an allowed domain?
How do I create an API key that is tied to a domain?
How do I secure an API by only allowing trusted domains?
Related Stackoverflow Questions:
These questions are related but didn't quite answer my question. Figured I would just put them here for future reference.
Google API Key and Domain Check
How does Google Maps secure their API Key? How to make something similar?
JavaScript won't help you here - the problem is that the key is being stored on the client, which means that it is not secure. You can make it a bit more difficult for an attacker certainly (e.g. like you say checking the referrer), but at the end of the day all the server can verify is that the key is correct, and since the key can easily be stolen that's not very helpful.
The way this can be secured is by having the private keys run on the servers of whoever you are giving them to instead of in the client. Depending on your needs, this may not be feasible.
One possibility to make it a bit harder for attackers is to use the site-locking technique to only allow the SWF to call the API if it is on an appropriate domain. See http://blog.boogatech.com/as3_tutorial_site-locking_your_flash_project/ for an example. Please note however, that this is client security - the goal with sitelocking is usually just to stop people from playing your game on other sites (and even then it can't stop the most dedicated of attackers). In your case you are dealing with server security - the server doesn't know about the SWF, all it knows is the arguments it is being fed, so an attacker can just bypass the SWF and the client security and call the API from somewhere else.
I'd advise you to think about what attack and attackers you are trying to prevent (why do you have to tie API keys to a domain?). This will help you plan your security attempts better. For instance, if you are not running an ultra-critical API, you can decide that putting in a couple of things to make it harder for attackers to access the API is acceptable, with the knowledge that you can't stop an extremely dedicated attacker.
I need my Flash client to communicate with a server securely (through binary sockets). For this, I was thinking of embedding a pre-shared key inside the AS3 code and exchanging XORed data through a custom protocol.
I am told that SWF decompilers do a good job at making all embedded code clearly apparent and readable. Does this mean that I can't really hide my key?
If this method is impractical, what other options are there? I have tried as3crypto, only to find that it's full of shortcomings and lacks serious documentation.
You cannot hide your key at all - SWF is totally untrusted, can be easily decompiled. It's pretty difficult to deal with security with SWF's because they run on the client and are not trusted.
It might depend specifically on what you are trying to accomplish with secure communication. For instance, if you are trying to secure a high-score system that is pretty much impossible because the game runs on the client (the SWF) and they can manipulate it to spit out any score they want to the server. Here is a good read on this: What is the best way to stop people hacking the PHP-based highscore table of a Flash game
If you can use the SWF only as a front-end UI and all logic takes place on the back-end, then you can secure your application (using the above highscore example, if the game was not an AS3 game but actually ran on the server itself, it would be a lot easier to secure, because the backend is trusted and cannot be modified or viewed by a user), but if the logic takes place on the SWF then you are pretty much out of luck.
I've been playing with HTML5 location lookups recently and its relatively straightforward to pull someones location from a device like an iPhone.
I want to write an app that uses location data, but its important that the location be factual. In other words I need to prevent people from authoring a fake post to the backing website / web service with mocked up GPS coordinates.
Is there anyway to collect GPS coordinates from a mobile device using the HTML5 geolocation apis and securely transmit that back to a web service in a way that someone wouldn't be able to author a post with the same data and "game the system" so to speak?
Not without some serious encryption on the payload on the client. Which if there is money involved, someone will reverse engineer and figure out how to create valid payloads themselves. Remember if there is money or fame involved then somebody will think the effort to do something like this is "worth it". If your web service is public and not using some kind of encryption nothing on the client will ensure that someone with a network connection can't sniff your protocol and fake whatever data they want. And SSL won't cut it. Anyone can proxy the SSL connection on their local network decrypt the payload and inspect it to their hearts content.
No. Completely agree with the answer from fuzzy lollipop. If you’re talking to a remote machine, the data can always be faked. Always always. What makes you certain you’re even talking to a mobile device at all? The User-Agent string? Pfft, it can be faked. Talking to a GPS? Pfft, could be coming from a predefined path. Talking to a web browser? Pfft, could be a bot, or some other malware.
And don’t think encryption (i.e. HTTPS) is going to help you. The client could edit any of your HTML, CSS, or JavaScript on-the-fly — take Firebug or Greasemonkey for example.
The reasons why you can’t trust the client are the same as the reasons why exploits such as SQL or HTML injection are so common. Ever heard the phrase “the customer is always right”? Well, the customer may be right, but the client is always untrustworthy.
The system is there to be gamed. As flaws are discovered, you patch them one by one. It’s more like leapfrog, rather than achieving the holy grail. Bruce Schneier’s quip “security is a process, not a product” comes to mind. Asking for a system that “can’t be gamed” is missing the point. What you need to be doing is creating a system where the server sanitises the data, and/or rejects bad data — fuzz testing is not a bad idea, either.
That’s about the best you can do without shipping custom untamperable mobiles to your customers with the OS in ROM, and the inside sealed with epoxy.
Is there a reliable way of preventing my actionscript code (as2 or as3) from being copied (e.g. if there's some IP in it)?
I know there are tools that can decompile flash code so it's easily reverse-engineered and I've also seen a few tools that claim to be able to obfuscate actionscript code in such a way that it's not steal-able, but I wonder how reliable they are...
Do you know? Thanks!
It is by definition imposible to prevent it.
The reason is simple, the code needs to run on the client, so the client needs to be able to read it.
The best you can do is to make so hard (time demanding) to do that it's not profitble.
Flash has a built in feature to protect againt decompiling with a password. I'm not sure exactly how it works, I guess some form of encryption.
You can try and spil sensetive data up and join it at runtime, og encrypt it and get the descryption key from the server.
But in the end there's nothing you can really do. Unless you wan't the users to input the encryption key (password or a file).
There is no build in encryption in Flash but there is a couple of free librarys like crypto lib http://code.google.com/p/as3crypto/.
I've found no reliable and sustainable way to obfuscate the code. If there's a way to obfuscate the code, I'd bet that:
it would affect the performance of your code
it would be just a matter of time before someone makes/finds a decompiler for that obfuscation method
I wouldn't consider a good practice to rely on the security of your client code. Even if the code couldn't be decompiled, the swf is run on the client and communicates with the Internet via a network connection the user has access to. The packets can be sniffed and all the data that's being transfered can be easily analyzed.
I think you should find a way to develop a secure application, even considering that the client knows everything you do. You should try to use server-side constraints and filter all inputs before using them. Also, requesting all the sensitive data from a server-side script, instead of embedding it in your AS code could be a good start.