I want to implement secure solution, which would prevent dumping password from memory after it usage. I tried few solutions, but even when i used all of them, i still can dump my password which should be erased from memory. My code:
char str[49] = "This is a string literal. See the double quotes?";
// cout << "Secret variable is: " << str << " with length: " << strlen(str) << endl;
cleanse(str, sizeof(str));
memset(str, 0, sizeof(str));
SecureZeroMemory(str, sizeof(str));
OPENSSL_cleanse(str, sizeof(str));
Even after using all of those functions at one time - in memory dump my secret variable appear
My compile params:
-s -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden -fuse-ld=lld -Wl,--gc-sections -fstack-protector
That's how i dumping memory using Process Hacker, then i'm using strings
to extract all strings from memory and here it is:
Value which should never appear here, what i'm doing wrong?
CodePudding user response:
In C
, string literals have type const char[N]
, where N
is the size of the string including the terminating null character. The effect of your line
char str[49] = "This is a string literal. See the double quotes?";
is to copy the string literal into the str
array at program startup. This creates a copy of your password in the str
array; the original string literal remains unchanged. And it is this original string literal that is found by the strings
app.
To get round this, you could initialise the str
array at runtime, from user input. But if you use a library routine like fgets
to do this, you have no control over what it does; for all I know, it might save a copy of the input line somewhere internally. So if strings
still finds your password somewhere in memory, you will have to implement your own character input handling.
By the way, you are creating problems for yourself by specifying the size of the str
array; if the string length ever changes, your code will fail to compile (or worse). Simpler and better is
char str[] = "This is a string literal. See the double quotes?";
which has the same effect.
CodePudding user response:
The process needs to be able to initialize that string when the function is called. Even if the value stored on the stack is cleared, it will still remain present in binary that was loaded. It is very important that you understand:
No matter what we add in the code, it won't be enough to stop a professional cybersecurity engineer from finding a password stored or generated within a binary without the addition of a separate key.
We zero the memory of a password because it did not exist prior to the start of the program so we can minimize the time it is held in memory. There is no safe way to store a password in the binary, but we can do some tricks to make it harder to find. We can pretend to have security by storing an encoded version of the password. However, it will still be difficult to store it in a way that prevents the compiler from optimizing the password back into its plain text form.
Ideally the password (or private key) would only be stored on a trusted system. This binary would be passed to untrusted systems which must send requests to the trusted system. The trusted system then acts on their behalf while ignoring malicious or malformed requests.
Side Note: This question may be the result of the XY problem. Why are you attempting to store the password? What do you actually want to do? There may be a simpler answer to your problem which does not require storing the password in a binary.