6

I'm developing a PHP application (PHP 7.3) for my company, which will be hosted in our own servers. For now it will only be accessible from within the network but eventually will be opened to the web.

The IT department is going to give me a "service" user whose password won't expire (so all the services for both the servers assigned to me and the app itself will keep on running forever) but they don't want that user's password to be stored in plain text anywhere in the server. To do that, the System Admin will have to input the password through a Remote Desktop Connection every time we need to make changes to the server services or such but I also need PHP to use that user's password constantly to access other resources on the network (LDAP server, other DBs, MS SQL DB and so on).

What I thought might work is:

  1. Having the password encrypted in a plain text file above the root folder of the PHP application
  2. Having a key in another plain text also above the root folder of my app but in a different folder
  3. Having a cypher in another file or maybe in my main configuration PHP file

Does this make sense? Or maybe I could also have the key encrypted and another key in a file to decrypt the first key?

I'm very new to encryption so any explanation or link will be very much appreciated.

CesarA
  • 63
  • 3

3 Answers3

1

I'm surprised that there doesn't seem to be a canonical question and answer or at least a duplicate of this on this site - but a quick search failed to turn up anything relevant.

(There is no OS independent answer to this question - but I will address Unix/Linux for various reasons not worth going into right now).

In order to use the password it must be accessible in an unencrypted form to your application. That means the user account under which your application runs and root will have access to the plaintext. Most likely it will also be present in backups of the system, and definitely will be present in VM snapshots.

So it is impossible to be completely certain that the password will not be exposed. That means that you (or the other relevant system administrators) should be taking taking steps to mitigate this. The obvious ones are:

1) Password Rotation this limits the window in which a captured password will be of any use to an attacker. In most cases, to get a seemless change, you need to alternate between two accounts - so one is in use while the other is getting changed. Surprisingly few people bother with this.

2) Token based authentication - the password bootstraps a change of single use tokens (and is immediately forgotten by the client). Deployment of this is even rarer.

3) The use of a machine identity is growing in popularity (due to the availability of the service in clud environments). To avoid a plaintext password being stored on a computer (or an equivalent substitute such as a private key) the infrastructure vouches for the client, e.g. by providing a signed attestation which can be presented in lieu of a password. This generally requires custom software at client and server to handle the authentication.

Given your current constraints then these are not very practical solutions - that you only have a single account, using off the shelf software and no control over the server you are trying to authenticate to. A further consideration is that, using PHP, you need a low overhead on whatever mechanism you choose to store the password. Although not ideal, the most practical solutions I can think of are:

4) use the Linux kernel key storage (assuming this is linux). AFAIK, there is not a PHP extension for this - so you'd need to run an external program to retrieve the password each time.

5) store the password in a file on a ram drive (with appropriate permissions). You could use shared memory instead but the tools for interacting with the file and its contents are more limited.

6) Store the password in the webserver runtime memory and pass it to PHP at runtime as an environment variable

7) store the password in an encrypted filesystem - there's a lot of choices here, but encfs is probably the least painful and easiest to integrate with the backup.

Note that the first three require that you provision a method for injecting the credentials at boot time (not sure how you would do this for the webserver), while encryption requires that you provide a decryption key at boot time.

symcbean
  • 18,278
  • 39
  • 73
0

You certainly shouldn't keep the file on the system in any folder that could be publicly accessible, as misconfigurations etc. could lead to the password being exposed.

Keeping the key on the server, even in an encrypted format, won't work either as you will need to decrypt it for use with PHP, so it will exist somewhere on the server in decrypted format, even if it's just in memory, which sounds like it falls foul of your admin's request. Since there are other resources available, you could ask IT to make an API available on the network which will act as a gateway to the other services you require access to.

For a real world demonstration you can look at how it has been implemented in the cloud in AWS infrastructure (via their 'Secrets Manager' service) or Azure's 'Key Vault'.

LTPCGO
  • 965
  • 1
  • 5
  • 22
0

I'm a bit confused by «The IT department (...) don't want that user's password to be stored in plain text anywhere in the server. To do that, the System Admin will have to input the password through a Remote Desktop Connection every time we need to make changes to the server services», an I think the gist of the problem lives previsely there.

It's quite normal to have service accounts with no expiry for applications. This account (or accounts) should be limited just to the resources they need access to.

This password could be stored in plaintext inside a configuration file (I don't think it's a problem, really), or be slightly hidden with some encrypted-with-a-key-somewhere-else obfuscation (what you suggest). In both cases, an attacker with whole access to the system (even just www-data), would be able to get hold of the key.

However, the fact that it is mentioned the System Admin would input the password through RDP every time, makes me think this would not fulfill waht your IT department is expecting. Note that with such approach, there would be no need to ever enter the passphrase more than once.

So you should clarify with your IT department how they want the password to be stored and used, and then proceed accordingly. Maybe they are fine with this approach. But they might be adamant that the password may not ever hit the disk (not even in encrypted form), and you would need to keep in memory at all times. Perhaps they didn't consider that you would need to bind many times to the AD. They might prefer to generate a separate account for accessing the LDAP and databases...

You may be able to make it work by having the credentials stored only in memory by a trusted process, and it may suffice for it to pass the in-memory secret (password) to another process, or it could need to perform the bind/login itself on behalf of the app. It may also be possible to use a kerberos token for the application access (but note it would have to be renewed periodically!).

Ángel
  • 17,578
  • 3
  • 25
  • 60