Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify POST data is sent from Android app with correct SHA1 signature?

Recently my game has been hacked and one user submitted an impossible score to the server. The score was submitted with a verified checksum, and correct data.

I'm convinced that the user must have reverse engineered my APK file to find the POST request.

Now I wonder what would be a good way to prevent this from happening again and I thought about verifying the SHA1 signature of the app. Maybe this way I can make sure that the app is signed by me, and is not a reverse engineered and changed version of the app.

Would this be possible? Or would there be a better solution to solve this?

I am using LibGDX by the way.

like image 289
Z0q Avatar asked Feb 13 '16 14:02

Z0q


People also ask

How do I validate my signature app?

Android Security Verifying App Signature - Tamper Detection We can break this technique into 3 simple steps: Find your developer certificate signature. Embed your signature in a String constant in your app. Check that the signature at runtime matches our embedded developer signature.

How do you fix your Android app bundle is signed with the wrong key ensure that your app bundle is signed with the correct signing key and try again?

Go to Build -> Generate Signed Bundle / APK. Select Android App Bundle. Enter your key-store details (if this is your first time doing this, you have to check the Export encrypted key checkbox, which you can use for Google Play App signing) and click Next.

What is Android application signature?

On Android, application signing is the first step to placing an application in its Application Sandbox. The signed application certificate defines which user ID is associated with which application; different applications run under different user IDs.


5 Answers

1) Use code obfuscation for ex. Proguard. This kind of tools available not only for Java. But be careful with that - obfuscated code may work slowly or contain additional bugs.

2) Add App Licencing check (this will check app signature with Google Play):

Watch this video with attention: https://www.youtube.com/watch?v=TnSNCXR9fbY As I remember he mention technics used at runtime to verify your app not hacked or modified (zip check, etc).

3) Make sure your app/server use secure connection (SSL/TLS) only with MODERN cipher suites. This will mitigate downgrade attacks.

You can use this generator to build config with MODERN cipher suites for your server: https://mozilla.github.io/server-side-tls/ssl-config-generator/

Also you can use certificate pining on client side - this will mitigate authority attack.

Do not use plain HTTP connection.

4) Use some kind of request signing (like Amazon AWS does) You can get core idea from their docs. http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html

Also this article should be helpful.

5) Prohibit usage of your app on ROOT'ed devices by adding run time check. Because of on rooted phone it's easier to hack or analyze your app.

6) You can decrease fraud by adding some ban system to your online game - if somebody hack your app and send wrong data to your server => add this user to ban list on server side (by IP or by user ID, etc). Probably add users to this list temporary (ex 24 hr, 7 days)

7) + if you are using Json/XML as data formats for network layer try to use binary format like Protocol Buffers. Binary serialization formats more efficient and hard to reverse engineer.

like image 56
dasar Avatar answered Oct 04 '22 06:10

dasar


First of all, you really have to obfuscate your code. You can find more information about ProGuard and code obfuscation here.

Second of all, you can use GoogleAuthUtil available in Google Play Services, which is available for devices running Android 2.2 or higher.

GoogleAuthUtil does exactly what you need:

GoogleAuthUtil server communication

Your client server calls go to Google via a HTTPS request, Google checks whether or not the call is made by an app signed with your release certificate, and then it sends the request to your server.

You can find official tutorials about how to implement this here and official documentation here.

Cheers!

like image 23
DDsix Avatar answered Oct 04 '22 07:10

DDsix


You can obfuscate your code better and use some very obfuscated secret to sign your requests. With that you can increase security.

But if all your game run in client it can't be completely secure. Because it doesn't matter what you use to sign, if you do it in client it means you have the secret or private key in client and then it can be hacked.

To make it more secure you need to involve some game logic in server and then control in that logic that the user isn't cheating.

like image 24
lujop Avatar answered Oct 04 '22 08:10

lujop


If you want to verify the signature of your app without the possibility that this is cracked too, you would have to upload the whole apk and make the check on a server. This is not a practicable solution.

The only secure android app is a pure terminal app, which means you'd have to do all computing on a server. Most of the time this won't be possible because of latency.

That's why we Android developers have to live with this: an app is not 100% secure.

But you can get close to it.

You might want to read Security with HTTPS and SSL guide for securing your communication.

Also you'll want to ensure your client is hard to crack: android app piracy prevention and Combating Android App Piracy: Xposed

In your case you'll also want to implement server-side request validation: If you have a game with a server side, users probably have an account. If a user sends a clearly impossible score, automatically disregard the request and ban the user (and his ip). (But also have in mind that this should never happen to a valid request, otherwise users might get angry and stop playing.)

like image 31
F43nd1r Avatar answered Oct 04 '22 08:10

F43nd1r


Verifying the integrity of your app won't be enough, since the request can be easily faked outside the app or modified in memory on the fly, using a rooted android environment. Even more, you cannot totally avoid it.

This is a problem shared by all applications running in a machine out of your control (all client applications). You can't never trust the data coming from them.

As I can see it, you have several choices:

  1. Obfuscate the code and make the app more difficult to be reverse-engineered. Notice that this do not solve the problem, but minimizes it.
  2. Move processing to the server. The more game-play is controlled by the server, the less vulnerable you app would be to this malicious behavior.
  3. Automatically detect impossible scores and close their accounts

Cheers,

like image 32
idelvall Avatar answered Oct 04 '22 06:10

idelvall