3

This is a repost, because i accidentialy posted on stackoverflow first

I was wondering how i could achieve a high security level, using Client-Server Authentication. Below is a rough draft of what i thought about: enter image description here

Let me explain it a bit more:

  • The C++ executeable is running on a gaming console which has an unique ID the user uses to sign up on my website
  • When the executeable is launched it will get the current module/file hash of the executeable and the unique ID ("Key" in the sketch) and do a webrequest to my website (example in blue on the sketch)
  • The auth.php on my website will then check if the file hash is the same as the file that was given out (detecting if the file was modified). It will also check if the "Key" is connected to a user
  • Then it will send back individual info from that user and also some data/offsets needed for the executeable to run properly later (This would prevent the attacker theoretically from just noping the internet connection, so he has to make a call to my website to get data that's needed to run the executeable properly)

Sounded good to me at the beginning but then i noticed some flaws:

  • Even though i'm obfuscating and encrypting the file a hacker will still be able to disassemble it. That mean's he could take out my check if the key is spoofed and just send the key of a registered user (he can also edit the hash that's sended to prevent the whole check if the file was modifed what makes it kind of redundant)
  • He could also read the data that's sended after a successful auth and then nop the internet connection, so there's no call to my website anymore and insert the data he got into the executeable to make it work

No matter of the security on the executeable a hacker will always be able to disassemble/decompile it at some point. That's why i think the Client-Server Authentication has to be so that even if the client is hijacked it won't be able to authenticate. I don't really know if that's even possible or if it's just the wrong approach.

I would really appreciate if you could leave some thoughts or ideas down below. Thanks for your time and have a good day :)

AndrolGenhald
  • 15,436
  • 5
  • 45
  • 50
ZZ_James
  • 33
  • 5

2 Answers2

2

You cannot trust the client, and your client-server authentication cannot work.

Any hacker can run an unmodified version of your software, capture all data he needs, and change the client executable later. Using an interception proxy will allow him to change the request and use the original hash of the file.

Or he can use a valid key, download the missing parts, patch the executable to include that parts, and skip the authentication.

Using TLS does not help, not even certificate pining. As he is in control of the connection, he can even change the client executable to allow his own certificate to pass the checks.

He will be able to authenticate no matter what. Your protections are only speed bumps, not road blocks. List of broken DRM schemes includes Sim City, Diablo, Battle Field, Doom, Assassin's Creed, Dishonored, you got it.

If even Ubisoft, EA, Sony, Microsoft, Konami and others could not deter attackers, you will probable be unable to deter them too.

ThoriumBR
  • 50,648
  • 13
  • 127
  • 142
0

I see a couple of possible threats:

  • Vulnerability for Man-in-the-Middle attacks. What if an attacker gets a valid hash, changes the file afterwards, and then does a MitM-Attack to replace the you generated of the malicous file with the one he calculated in the first place? In your setup this should succeed, although he tampered the file.

  • Authentication via HTTP URI Query Parameter is not a good idea, since those could be found in various log files or the browser history.

  • As you already pointed out, everything you store on a client cannot be trusted like server-side files, since attackers can modify them in any way, and can extract key-material. This may be trivial or not, but you have to assume that it's possible.

To mitigate those threats you should:

Use HTTP Authentication Header

Instead of sending authentication information via HTTP Query parameter, pass them using HTTP Auhentication header. Like:

GET example.com Authorization: Basic base64(userid:userpass)

Instead of GET example.com?auth=xxx&hash=xxx

Since you already have some kind of API Key (auth parameter I suppose?) which is bind to a user, you should take a look at OAuth2.0. It's a well-established approach of authorizing clients to act on behalf of a user.

Use TLS

Transport Layer Security is necessary to ensure the confidentiality of the connection. This way you can be sure the client talks to your server using encryption. If you need more security, also enable mutual TLS authentication (i.e. the client also needs to authentiate).

Sign the files

The only way to detect tampered files on the client is to sign them on the server before you send them to the user. Your C++ Application must check if the signature is valid before executing the file. If you have enabled a TLS connection you should already be in possession of the required keys.

  • Mostly true - but basic HTTP authentication is trivially susceptible to replay attacks (but on a default config it doesn't appear in the logs). For games, latency is a killer - so https *might* not be an option. Using TOTP in the request (and optionally a PHP type session for subsequent requests) and encrypting the response might be a better fit. – symcbean Oct 06 '17 at 14:05
  • 1
    @symcbean on modern hardware, there really isn't a significant performance hit from HTTPS – multithr3at3d Jan 03 '18 at 17:07
  • @multithr3at3d: speed of light is still the same (last time I checked). – symcbean Jan 04 '18 at 16:54