11

We're building an application that needs to log into a website using built-in credentials. It's not optimal to say the least, but we're stuck with "knowing" the username and password beforehand (hence stick them into the application somehow) and can not rely on runtime user information.

So I went through this StackOverflow article which basically represents my case and the answer seems to indicate that the best possible approach is to at least encrypt the password with a known key and store this key in the application in an obfuscated way.

My follow-up question now is: How do I best obfuscate this key so that it isn't visible in a file dump of the executable? Are there best practices for that as well?

9
  • 24
    This appears to be an xy question. Whomever made the decision for this to be the authentication method needs to justify why they are choosing x over security. The issue with obfuscation is that it pretends to be security when it is not. If you are going to disregard security, you may as well keep the access keys easily accessible to minimize support calls. Can you explain why you need to have the website be behind authentication? That may direct you to a better answer. Commented Oct 26, 2023 at 20:51
  • 6
    Have you considered creating a proxy service for this? You will still have the problem that anyone can consume it, but issues such as rotating the password become trivial. If your app requires (real) authentication for other purposes, it may even be possible to use this to improve the security of the solution. Commented Oct 27, 2023 at 6:48
  • 3
    Isn't the user of the software authorized to do everything that the username and password allow you to do anyhow? If not, you have a completely different problem. Commented Oct 27, 2023 at 7:14
  • 2
    ...that said, the threat model being an attack on A is very different from it being an attack performed by (or in cooperation with) a customer or reseller, which is more usual and what I assumed when seeing this question. I don't know why obfuscating a built-in key in software issued to B is even part of your concern; how would that make attacks on your hosting provider harder? If someone successfully attacks your hosting provider, they have whatever keys the customer's client is authenticating against. Commented Oct 27, 2023 at 13:58
  • 1
    Just to make sure: With "application" you mean something which is distributed to users, not something running on one of your own servers? Commented Oct 28, 2023 at 20:59

5 Answers 5

43

Hard-coded credentials are considered a vulnerability. Cisco gets caught time and time again, and have to issue a fix to remove them every time.

No matter how many layers of obfuscation you employ, the credentials must be deobfuscated before being used, so an attacker can grab the plaintext of the credential by using debuggers or disassemblers. You cannot stop this attack, you can only delay it.

Other downside of storing the credentials on the executable is that isn't easy to change the password: you will have to generate another executable and have the user download and replace the old one. This can lead to attackers sending an executable to the user by email or social network claiming to be you and offering a new one.

If all your clients use the same password this will be even worse: if one user leaks the password, you will have to revoke the credentials for every single client, and issue a new executable for everyone.

Every password should be unique and easy to replace. You can generate a key, store it on some file, and send the password to the user out of band. This way the user can replace the password if it gets compromised, you don't need to generate another executable, and every user gets a different password.

11
  • 1
    They key is stored, but there's one key for each client, and one password for each client. An attacker cannot grab one key or password and attack every single client you have.
    – ThoriumBR
    Commented Oct 26, 2023 at 12:40
  • 3
    No, you won't. When app starts, it checks if there's a key and generates one if there's no key. Then it checks if there's a saved password and asks one if there's no password, and saves encrypted password on the file. It then decrypts the password and authenticate on the website.
    – ThoriumBR
    Commented Oct 26, 2023 at 12:53
  • 3
    The best approach is to never save the username or the password. You only use them to log into the website and get a token or at worst a session cookie. Then you store that, in clear text. Locally encrypting a secret is useless (cfr: white-box cryptography). Use the OS to protect your app's local files (e.g. run as a different user/integrity level). No need for encryption, if somebody can read your app files then it's running in the context of your application and can easily get the encryption key anyway (either by reading it from a file or from the application) or the plaintext. ... Commented Oct 26, 2023 at 18:25
  • 11
    ... Every infostealer I've reversed has a big list of applications and their hardcoded encryption keys or filenames where to find them. Seriously encryption adds nothing here. Use permissions and impersonation/suid. You can use encryption on a backend where you have staff running as a privileged user. Commented Oct 26, 2023 at 18:25
  • 2
    @glades Then you need to set up a web app, with proper authentication and a limited set of actions accessible through an API, and this web app needs to call the backend. Handing out a password which allows anyone on the internet root access to your backend isn't an option.
    – niemiro
    Commented Oct 28, 2023 at 10:20
8

log into a website using built-in credentials.

Going over HTTP(S) is always going to be an enormous hurdle to any obfuscation, especially if the website you are logging into has a regular username/password field that takes a POST. That traffic is not intended to be hidden from the computer owner who can easily supply their own trusted CA files or try any number of other snoopy things.

It may be the username and password are not actually that essential to security, but if they are you need to run a proxy style service. That would absolutely hide the credentials from the client and would also allow them to only perform specific actions with the authorization granted by the credentials.

2
  • How does using a proxy style service help? If the service requires credentials to login, it only re-frames the original issue. If it doesn't, anybody who can access the application will automatically be able to access the website that ought to be protected. Commented Oct 30, 2023 at 3:39
  • @fatpenguin Only the proxy holds the credential of the third party website and can implement whatever access restrictions that the client-side app is hoping to do on the client-side now. The proxy api could implement any client authentication method, even something simple such as a plain key. Crucial difference is that if that key is stolen, the attacker could only do things they were allowed to in the app anyways! It is a pretty common pattern in web development. Commented Oct 30, 2023 at 7:00
4

Don't bother with the app - check the data instead (if you need to)

Really, the only use case where you'd care about this kind of login is if the server has to trust the data produced by the app - and by extension, has to trust the app to be your app and not someone else's hack attempt. As has been demonstrated countless times, this is literally impossible. However you obfuscate it, someone will break it, given enough incentive (or just a lot of free time and boredom).

This isn't a new problem though. A perfect example of this kind of problem would be aim-bots in online gaming; or perhaps the regularly-reported data sent back to Pokemon Go about the number of steps you've taken. It's not possible to prevent people hacking these systems, because ultimately the data has to get back somehow, and there are incentives in gameplay for people who do. The solution taken by games designers is to check what comes back from the app and see whether it's valid. If moves are too straight and accurate to be human, it's probably an aim-bot. If your number of steps coming back to Pokemon Go is unachievable within that time at the maximum walking speed, it'll be rejected. Clearly this checking process can be complex, but this is one way you can solve it.

But then you also have to ask - does it really matter? My company makes industrial microscopy equipment. We simply don't care about secure connections between our controller boxes and apps on a controlling PC. Sure, a suitably dedicated person could spend some time and find the secret commands we use to calibrate the system. But the result then would be a system that no longer works properly, and we certainly wouldn't repair/recalibrate the system under warranty. There isn't a benefit to the user to do this, and it'd cost us time and money for something which isn't a benefit. So we don't bother.

Or quit now before the lawyers find you

If it does matter that this data is held securely - in particular, if it's about bank details, government files, or personal details under GDPR in Europe, COPPA in the US, or anything similar - then be afraid. Very afraid. The most likely potential consequence is "merely" your company being sued for every penny it has, so forget about that last cheque. That's the best outcome. If you play f***-around-and-find-out with bank details or government files though, that's serious jail time. And depending on where you're working, if you're the senior engineer then you may have to sign off personally on the work, which leaves you personally liable and not just the company.

If your management are suggesting this, your only option is to refuse. Your bosses can only give you instructions to carry out work that's legal, after all. If that doesn't cut it, leave now. (And if you're feeling so inclined, consider whistleblowing.)

1
  • +1 for "quit now before the lawyers find you". An employer asking you to do this is probably breaking the law (and asking you to do so too). Commented Oct 29, 2023 at 16:56
3

How do I best obfuscate this key so that it isn't visible in a file dump of the executable? Are there best practices for that as well?

There is a system where you encrypt your key using AES, and the application decrypts it again. However, the application doesn't have a general-purpose AES algorithm and they key in a string, but it has the key compiled into the algorithm. This way, it is pretty hard to determine the AES key.

Unfortunately, I cannot currently find the name of this mechanism or the product that offers this. White-box cryptography

2
3

Security becomes more challenging in this area, but this is a legitimate question. You should look very carefully at the scenario to see whether additional user or device authentication are possible; and perhaps provide more detail in the question.

  1. Ideally you authenticate users (having had them register first) and login individually with user credentials. Any bad actors can then be locked out on an individual basis.

  2. If you can't register users, you should definitely look into registering devices. Obtain a unique identifier from the device on first startup, register that with the server to obtain a permanent key, require admin approval of the device (eg. by model & serial number) and use the permanent key to authenticate when connecting.

  3. Less preferably, you can register groups (eg. corporate installs) & distribute a unique secret to them. This can be a license key to be pasted into a dialog, or a file placed in the install directory. Software compliance works better when you are also notified of which devices are running it.

  4. Really you want to register and authenticate either users, or devices. You will find yourself in silly situations if you do not.

  5. If you have nothing unique locally, consider generating a nonce locally on first use & registering that with the server to get a secret key.

  6. Lastly, you can obfuscate secrets within an application binary; this will block unskilled actors but not a reverse engineer/ cracker. The approach here is to combine stored factors with computation in a non-obvious way; this prevents actors from reading your secrets directly from the binary. (Though unless you are skilled, they may be readable from a memory dump.)

Approaches to obfuscate secrets within the application binary:

  • Combine stored factors from more than one place; eg. one key from the binary, one key from an install license file, perhaps an initial vector elsewhere in the binary or constants in instructions.
  • If you can add in device- or user-specific factors, these will make the secret far stronger and prevent a breakage being used to attack other devices.
  • Use standard cryptographic primitives (eg. SHA256 hash).
  • Combine parts by hashing; using loops and a non-trivial structure of parts. Eg. several of this keypart, a few of that keypart, a constant text from somewhere else, hash in some instruction constants etc; perhaps spread this over two levels of looping with some parts in the inner, some in the outer loop. Use thousands of inner loop iterations total (say 10k to 100k).

The above approach will prevent a secret key from being readable from the binary or filesystem. However the complete key will still be formed in memory; and potentially readable if an attacker has access to a memory dump.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .