NSGangster
NSGangster

Reputation: 2447

How to "zero out" and ensure deletion of a string from memory

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:

Microsoft's Dispose Docs

String Marshaling

Unsafe Code

System.String Class

TLDR:

  1. 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.

  2. 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

Answers (2)

NSGangster
NSGangster

Reputation: 2447

Accepted @barac340 answer as it was essential in helping me understand memory management in finding my solution.

  1. I just use SecureString, with a single method that both sends it out through encrypted channels and then deletes the SecureString passed in.
  2. I use the 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.
  3. I then dispose of it, freeing up a bunch of null characters for garbage collection. :)

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

barac340
barac340

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

Related Questions