Recently the security team has informed me that there’s sensitive data/ password stored in memory.
For the password input, I’m using TextInput onChangeText to do a setstate for the password string before passing it to the API service payload (object with password string) to authenticate the user. Together with redux and redux thunk.
The security team recommends to change the string to char array. I’m not sure how to go about it, since in the end I still need to pass the password string to the API payload and hence the sensitive password string will still be stored in the memory. Another recommendation is to encrypt the string, is it even possible to do this in memory? I’ve encrypt the API call before sending it out, but I’m not sure how to encrypt it in memory.
To detect the string in memory, I’m using a jail broken iPhone with fridump to dump out the memory and use it with -s flag to extract the strings to a text file.
First, a few words about "security concern". The alert here is that the password, after being entered by the user, is, obviously, contained in device memory (not even on a disk yet as suggested by another answer, but memory as in RAM). Since Javascript is running in JSC, which is basically a C++ program, JS strings application creates while operating are stored in heap - a section of memory where all raw data goes. To oversimplify things, when you enter "hello world" as your password, the "hello world" string is created and stored as a whole somewhere in that heap. When you dump device memory you can scan it looking for hello world
sequence you just entered and conclude the app is "not secure" if you find it
Is that a real security concern? I don't consider it one, because if intruder has an access to another user's device memory to "read unencrypted passwords" then chances are he doesn't even need to do that, as there are much easier ways to steal that password (record screen, or touches, or keyboard strokes, or network traffic, for example). Most of the apps never care about this kind of thing as most of the security (memory safety in this case) is usually handled by the operating system (for example, by ensuring that one process can't just read another process memory that easy). These safety guidelines are usually applied to lower level programs that run not on mobile device but on, for example, ATMs, or servers, where there is an actual risk of intruder physically plugging into the device and dumping memory unnoticed.
Let's discuss how you can still avoid this so-called vulnerability to satisfy your security team. One of the easiest ways is, instead of storing password in a single string, to store it in an array, so instead of hello world
(a single string in heap) you have ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
(9 different one-letter strings (referred to as "characters" in other languages) stored somewhere randomly across the heap with one array object containing a reference to each of those strings). Now if you dump your memory, you wouldn't be able to find your initial password in there because it's scattered all over the place. How do you implement it in React native? Instead of storing password somewhere in state in form of string, use an array. In onChangeText append or remove items from that array, avoid concatenating entire string together until you actually need to send it over to a server. In order for asterisks to properly appear in your TextInput, you can create a fake string, since it's going to be masked out anyway, and only thing you care about is really just length of that array so you can draw the same amount of asterisks in TextEdit. Of course, finally concatenating entire string is (almost) unavoidable, as you still need to send it over to the server, but the window for that string should be relatively short - from constructing request and sending it to the point when GC (garbage collector) clears the string as the reference to it (the variable you had that held the string inside of it) is out of scope and is not accessible anymore