Reputation: 2447
I understand the main concept of garbage collection, about how once a specific object has no more pointers referencing it, it is "garbage collected".
Does this mean it is freed up but it's value is still available for someone with a debugger/disassembler to read (at least until that address is written to)?
I know with most objects (those implementing IDisposable
interface in C#
you can call the Dispose()
method and be pretty confident that memory can never be accessed again. But what about strings?
I know with garbage-collection (in iOS it's known as ARC
) once you get to 0 references the object "disposes" of itself. I'm worried that my application (tons of legacy code I took over) has tons of memory leaks with strong references and I do not want PCI sensitive data to still live in memory long after I've "set the String
to null
". Does setting the string to null put a null terminating character for every char in the string?
Here's some links to some research I've done so far and I think maybe what I'm looking for might be writing/re-writing after I'm done to unmanaged memory:
TLDR:
I know I can just set the String
to null
but I still don't trust that my application has no sensitive data living in memory that can still be referenced by a malicious party.
How do you guarantee (from code/unit tests hopefully) a string cannot EVER be referenced again from memory (even from a malicious 3rd party).
Sorry if I'm being paranoid I've just seen so much bad memory management (most of it from a deeply embedded third party framework) in this code base.
Upvotes: 0
Views: 1589
Reputation: 2447
Accepted @barac340 answer as it was essential in helping me understand memory management in finding my solution.
SecureString
, with a single method that both sends
it out through encrypted channels and then deletes the SecureString
passed in.Marshal
class to rewrite null characters over each
byte for the the byte length of the SecureString
starting at the memory address
of the SecureString
in unmanaged memory. I do want to clarify that it is a known issue on Xamarin.iOS that the memory address of SecureString
is NOT encrypted on secure string, so even though memory is freed up for GC with use as is, it could still be available in plain text through memory inspection.
I did NOT create a custom class, not because it wouldn't be beneficial for reuse, I just only use this in one spot in this case. And most my "future" use-cases would require disposal of said string after the first "get" of the actual String
value of SecureString
. So for now I just put the disposal in the function that uses the string. Specifically because I'm already using Marshal
to read the String
, it made sense to write to it after use in the same method.
Should the need arise for a custom class, for what I'm dubbing "ExtraSecureString", I will do so.
Upvotes: 0
Reputation: 26
I understand the main concept of garbage collection, about how once a specific object has no more pointers referencing it, it is "garbage collected".
Almost. The main point is that the object is not garbage collected right away after the last reference to this object was destroyed. After that object is in a pending state and is waiting for garbage collection process to be started.
Does this mean it is freed up but it's value is still available for someone with a debugger/disassembler to read (at least until that address is written to)?
Yes. As I mentioned above, freed objects are still in memory and wait for GC to start. Because garbage collection is non-deterministic, you do not know precisely when the garbage collector performs its work. Moreover, you can still obtain a reference to this object (through Finalize method Finalize override docs link)
I know with most objects (those implementing IDisposable interface in C# you can call the Dispose() method and be pretty confident that memory can never be accessed again. But what about strings?
The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. Disposing of a managed object doesn't mean that this object is releases - Dispose only change the internal state of this object (for example it frees native bitmap reference), but the object remains the same - it consumes memory, it still can be used, you can call its methods, etc. Only GC removes an object from memory. Thus, as a string is a managed object, it is released by GC.
How do you guarantee (from code/unit tests hopefully) a string cannot EVER be referenced again from memory (even from a malicious 3rd party).
IMO, the solution is to implement your own string wrapper with a dispose-like feature - for example, after you use an instance of this wrapper class and it is no longer needed you can call Free() method and your implementation will rewrite the value of an underlying string in memory (in either safe or unsafe context). But it requires accurate resource management. Also, string rewriting should be called by Finalize() method to ensure memory zeroing after the object was GC-ed.
Upvotes: 1