0

I have a web app that I use to run exe programs but the exe programs require a password to be passed. Currently this password is hard coded into the web app file in clear text.

Since this is not secure and I have seen other web apps do this. I am wondering, how do I securely store the password in a file or database that can't be viewed in clear text but when needing to run the exe, it can retrieve the securely stored password and run the program.

(web app is mainly PHP and database of MSSQL)

James
  • 1
  • 1
  • Related: https://security.stackexchange.com/questions/12332/where-to-store-a-server-side-encryption-key – mti2935 May 24 '22 at 01:25
  • Unless you want to prompt the user for a master key/password each run I think the best you can do is encrypt it using as a part of the key the machine's serial number. (you read that from the motherboard when you encrypt/decrypt...) If this is Windows you can just use "DPAPI" for this. That way the key is not exposed by the code. (though it could be exposed in memory) – pcalkins Jun 24 '22 at 19:21

2 Answers2

1

Given that you say "exe programs" and MSSQL, I assume this is Windows? In that case, you can use DPAPI (the Data Protection API) to encrypt (and decrypt) passwords (or other sensitive data) in a way where the OS handles the key management and ciphers for you. You'd call CryptProtectData (or one of its variants) and store the result in a file or in the DB, then read the encrypted secret back out and call CryptUnprotectData to get the password back when you need it. You could also use encrypting file system (though that isn't available on Home editions of Windows) or use the Credential Vault (which is just DPAPI + data storage in a single API).

Mind you, I don't know if there are PHP bindings for those APIs. Legacy DPAPI and modern CNG DPAPI, setting the Encrypt flag on a file, and accessing the credential vault, are C APIs. There are bindings for them in .NET and many other languages/frameworks, though, so probably there's already a PHP wrapper for them.

Note that none of these options are truly that secure. The keys used for DPAPI and EFS are protected by the password of the account in question. If you run the webserver as a passwordless service account, then the keys aren't really protected; anybody with admin access (or physical access to an unencrypted drive) can extract them. If there's a password on the account but the service manager supplies it automatically, admins or those with direct drive access can extract the password from the service definition. In both cases, the threat model is the same as if you just stored the password in a file that was only readable by the web server; it just requires more steps for the attacker, not actually more secrets or access.

If the web server runs in your user session then DPAPI/Vault/EFS uses your own password for protection, but so does everything else running under your account and if there's any malicious code it can just call CryptUnprotectData on the encrypted blob, or use debug APIs to read the secret out of the server memory. Still, if you don't run any malicious code (at least, not under your own account), this approach would at least protect your app password from attackers while your account isn't logged in (unless they can guess or brute-force your password).


Fundamentally, no option is going to let you securely store a secret in a way that some code running on your machine can access, but no other code can, unless the accessing code (the web app/server) can be given a secret that no other code can use... which just kicks the can up the road. Might as well require that the password be supplied to the server when it starts, then, and avoid storing it at all. There's no silver bullet for secret management; it's secrets (usually encryption keys) all the way down. If you want to start some code automatically without needing to supply a secret, then that code fundamentally can't protect data in a way that somebody else - also without the secret - can't break.

CBHacking
  • 42,359
  • 3
  • 76
  • 107
  • Since PHP isn’t windows specific, and there is no direct alternative on other OSes for this API, I don’t think a direct module implementation exists… what does exist is this github.com/vincepare/DPAPIbridge a tool you could exec from php to acces the secret for you. I have not reviewed this code nor do I make any recommendations. – LvB Oct 22 '22 at 08:59
0

I believe what you're looking for is a way to encrypt and decrypt the password. There are algorithms that allow you to encrypt a string and reverse the encrypted string to get the original one: Encryption algorithms, while some do not: Hashing algorithms

Since you're using PHP, you can use the in-built function openssl_encrypt to encrypt and openssl_decrypt to decrypt it

string openssl_encrypt( 
  string $data, string $method, string $key,
  $options = 0, string $iv, string $tag= NULL,
  string $aad, int $tag_length = 16  
)
# Returns a boolean
string openssl_decrypt( 
  string $data, string $method, string $key,
  int $options = 0, string $iv, string $tag, string $aad
)

Example:

$string = "My password";

$ciphering = "AES-128-CTR";

$options   = 0;
$encryption_iv = '1234567891011121';

$encryption_key = "YOURCUSTOMKEY";
$encryption = openssl_encrypt($string, $ciphering, $encryption_key, $options, $encryption_iv);

$decryption_iv = $encryption_iv;
$decryption_key = $encryption_key;

$decryption = openssl_decrypt($encryption, $ciphering, $decryption_key, $options, $decryption_iv);

echo "Original => " . $string;
echo '<br/>';
echo "Encrypted => " . $encryption . "\n";
echo '<br/>';
echo "Decrypted => " . $decryption;

For this to work, the key you use to decrpyt should be the same as the one used to encrypt or the results will be different. So the key $encryption_key should be not accessible to anyone else.

Cypherjac
  • 101
  • Is there a way to securely store the encryption key some where? – James May 23 '22 at 21:21
  • You can store the encrypted password in the database. For the key you can save it in the database as well, since you're the only one who can access it.. or even just within the code as a variable.. since PHP is a server-side code, it won't be visible to the client – Cypherjac May 24 '22 at 06:05