4

I have created a variable in C#. Now I want to clear the variables value from the computer memory. Is there any way to do that?

Below is my current attempt at deleting the value of recordLine, but I can still read the value from memory with DumpIt even though I set the variable to null and call garbage collection.

private void Extract_SLST_VariableLine()
{
      StreamReader file = new StreamReader(FilePath + FileName);
      while (!file.EndOfStream)
      {

            string recordLine = null;
            if ((recordLine = file.ReadLine()).Trim() != string.Empty)
            {
                  console.writeline(recordLine);
            }
            recordLine=null;
            gc.collect();

      }
}
Anders
  • 65,582
  • 24
  • 185
  • 221
Akash Daniel
  • 41
  • 1
  • 1
  • 3
  • 2
    You can reboot... – ThoriumBR Jul 04 '19 at 10:30
  • I don't know Garbage collector working or not but the values are retrievabale while using dumpit.exe – Akash Daniel Jul 04 '19 at 11:23
  • Similar question for Java: https://security.stackexchange.com/questions/148282/passwords-in-memory-practical-ways-to-improve-security – Anders Jul 04 '19 at 11:25
  • @ThoriumBR Rebooting only works if the page containing the data wasn't written to swap space, or it was and has subsequently been overwritten and the overwrite actually caused the data on the media to be overwritten (SSD wear levelling, I'm looking at you). – user Jul 04 '19 at 13:31

4 Answers4

4

Just setting a string to null or calling the GC will not help here. It might delete the reference to the value, but not the value itself. After GC, it may be overwritten, but there is no guarantee that it will happend anytime soon.

What you need instead is something aking to a SecureString, that implements a Dispose method and some obfuscation. However, the security it provides is limited:

We don't recommend that you use the SecureString class for new development. For more information, see SecureString shouldn't be used on GitHub.

SecureString is a string type that provides a measure of security. It tries to avoid storing potentially sensitive strings in process memory as plain text. (For limitations, however, see the How secure is SecureString? section.)

The problem here is that if there is sufficently advanced malware with sufficiently high priviliges on your system, no secrets are safe no matter what fancy C# types you wrap them in. So I am not sure this is a problem with a solution.

If you do use a secure string, think about how you get the value into and out of it. If it passes through an ordinary string, you have gained absolutely nothing.

Anders
  • 65,582
  • 24
  • 185
  • 221
0

To a first approximation, you can't. There's technically ways - things like SecureString (deprecated) or P/Invoking SecureZeroMemeory - but the problem you're trying to solve is hard to solve in user-space programs at all, and much harder still in memory-managed runtimes like .NET (or JVM/CPython/Ruby/Node/PHP/etc.). Garbage collection can copy values around such that their current location when you delete them isn't the only place the value exists. Memory can be paged out to persistent storage and not erased from there. For that matter, a malicious process could read the data out of the program's address space before it's erased...

What, you think the last is implausible? Then why are you worrying about this at all? Without high privileges, a process running under user A can no more read dump files from a user B process than it can read the user B process' address space directly. Besides, you can turn off dumpfile generation. With high enough privileges, you can read the address space of any other process directly, in real-time (or close enough) - this is how debuggers work - and copy any data you want to anywhere you want (and also control the program flow to do whatever you want it to do, with secrets or otherwise).

In other words, if your threat model doesn't include "malware running either as the current user or as a highly-privileged user", you don't have to worry (at least so long as you aren't creating memory dumps and leaving them in insecure locations, including on any unencrypted drive that an attacker might have physical access to). If your threat model does include such attackers... you've already lost, pretty much. There is extremely little that can be done in the face of such things, and what there is, mostly involves moving code execution off the main processor and out of OS-readable memory entirely.

CBHacking
  • 48,401
  • 3
  • 90
  • 130
  • Citation needed for "a process running under user A can no more read dump files from a user B process than it can read the user B process' address space directly". Consider that this is exactly how a Microsoft Azure signing key was disclosed. – Ben Voigt Sep 22 '23 at 20:20
  • I mean, sure, if you move the dump file to an unsecured location, it can be read. But by default they are created in a secure location, and moving anything sensitive to an insecure location is a far more obvious, and easily-prevented, failure than generating crash dumps but ensuring they never contain sensitive data! – CBHacking Sep 23 '23 at 03:52
-2

C# handles garbage collection automatically, you can call it explicitly with GC.Collect() however it is considered bad practice.

Below is a far more succinct and detailed explanation than I am equipped to give.

Alternatively why not just overwrite the variable with a dummy value? You could use null I guess but you would have to be careful of causing an exception and add in checks accordingly.

Then call GC.Collect() to clear the now unassigned data from memory. Whether that actually work or not I'm not sure.

EDIT: Based on comments below it does not.

See slightly ugly example...

var foo = 'sensitive';
// Your code
foo = null;
// call GC.Collect()

What's so wrong about using GC.Collect()?

GC.Collect() documentation

Pang
  • 187
  • 7
3therk1ll
  • 147
  • 1
  • 2
  • 12
-2

As the variables store the memory on the heap If we assign variable to null it will just change the pointer and access the null reference with out deleting the previous variable it applies to even reassigning the variable also. Using IDisposable interface in C# we can remove the variables details from the memory by calling the garbage collector manually.

The below code will call the Dispose function and collects the all variables from the class and remove.

Public class Process : IDisposable {

private void Extract_SLST_VariableLine()
{
    try
    {
        StreamReader file = new StreamReader(FilePath + FileName);
        while (!file.EndOfStream)
        {

            string recordLine = null;
            if ((recordLine = file.ReadLine()).Trim() != string.Empty)
            {
                console.writeline(recordLine);
            }
            recordLine=null;
        }
    }
    catch()
    {
    }
    finally
    {
        Dispose();
    }
}

}

 public void Dispose()
 {

        GC.Collect();
        GC.SuppressFinalize(this);
 }

For more reference you can find in the follwoing links.. https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

anvesh
  • 1
  • 1
    The GC collection doesn't delete the value, it just tells the OS to reuse that area of memory. The value is still there in memory, your code just no longer has any direct handle to it. –  Jul 11 '19 at 15:51
  • @NicHartley any other way to delete the values from memory permanently ? – anvesh Jul 15 '19 at 18:00
  • 1
    Read the current top-voted answer on this question. –  Jul 15 '19 at 18:01
  • @NicHartley I have a requirement where I get the credit card number with other details in a json from API call. so I have to store the details in variable. and then I have to read 7th digit of the card number. The top-voted answer doesn't suit to my requirement. Any other solution? – anvesh Jul 15 '19 at 19:16