2

Problem: How to forcefully overwrite system-memory in Java - More specifically: When secure keys must not stay longer than a few seconds in the memory: Neither in the jvm-memory, nor in the OS-Memory?

What I tried: Modifying the java garbage-collector implementation, so that it would for sure overwrite objects with random bytes, instead of just freeing them. However:

Everything I read about System.gc() showed me that I can never really rely on it, and that one should not use it in production. However, what if I know that I use a specific JVM? What if I know that I want to use the OpenJDK with Java 11 and that I configure the JVM to use a specific GC Implementation (to not let the JVM choose the GC)?

Question 1: Can I then somehow be sure that System.gc() will trigger garbage collection 100% times?

Question 2: Can I find out, what's the maximum duration between System.gc() has been called and the actual garbage collection will start? This is a significant part of the question! I could only find answers to the garbage-collection-efficiency itself (e.g. the throughput vs stop-the-world pause-times), but that is NOT the answer to this question. (Read myself through the whole documentation here)

Question 3: If the idea with the modified garbage collector is by far the worst idea to securely overwrite each occurence of various sensible java objects in the memory, then how could I otherwise overwrite those objects in the memory? Is it even possible with Java? It would be nice to be able to delete and overwrite these objects directly in the java-code, similar to freeing objects in C/C++? Are there other possibilities maybe outside java where I can overwrite each occurrence of such sensible information in the memory, which would have to be triggered as instantly as possible as soon as the java object is no longer in use?

My research so far:

As you can see those are, except for the official docs, quite old, so:

Question 4: Are there any newer insights available to the concern whether System.gc() behaves the same like 10 years ago?? Thanks!

*EDIT: I already use byte-arrays for the cases where those can be used. The question is about more complex Java-Objects with various different fields and properties, which have to be cleaned completely in the memory.

ElectRocnic
  • 1,275
  • 1
  • 14
  • 25
  • 2
    There is a fundamental misconception in your question. It’s not only that `System.gc()` is not guaranteed to do a garbage collection, it is also not guaranteed that a single garbage collection cycle will identify all unreachable objects. But even if it does, reclaiming the memory just implies making it available for new allocations. It does not imply zeroing the memory. As long as the memory does not get overwritten by newly allocated objects, it may contain the old objects’ values for an indefinite time. In the case of manually triggered gc, the likelihood of overwriting is rather low. – Holger Dec 14 '18 at 15:14
  • Yes, but like I explained, the GC Implementation has been modified/patched, so it would definitely overwrite values indeed! But thanks for your input! – ElectRocnic Dec 14 '18 at 17:15
  • If you have modified the garbage collector, any question on Stackoverfow about its behavior is moot, as we would be discussing about different software. It’s kinda strange that you are saying you dug deep enough into the source code of the garbage collector and are confident that it will do the intended thing, but then ask *us* about the gc behavior. Anyway, if an attacker can read your heap memory, all these efforts are pointless anyway, so you should rather spend your efforts on preventing attackers from getting so far. – Holger Dec 17 '18 at 08:30
  • Thank you, the question was also about alternatives, and/or if somebody has tried similar things in the past. You are right in some way, the intention was to find out if I overlooked something (Could not find out yet how long it takes between `System.gc()` and the invoke) - Basically my current approach is to empirically test it to get statistics about this specific time costs, and yeah, self-made tests already proof that `System.gc()` will indeed trigger the gc. That's just not the way I preferred at the beginning hence the question – ElectRocnic Dec 17 '18 at 16:53

1 Answers1

4

Assuming you can store the security key in a byte[] or other primitive array it should be enough to zero the array after the key was read:

for (int i = 0; i < key.length; i++) {
  key[i] = 0;
}

Above should result in byte[] key being fully overridden. Relying on GC here would be a mistake as it's unpredictable.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • Thanks, I already use that for keys which can be stored in byte-Arrays directly. Maybe should have mentioned, that the question is about more complex Java-Objects/Classes, which cannot solely rely on byte-arrays. Is there an option for such cases? – ElectRocnic Dec 14 '18 at 13:51
  • 3
    There is no guaranty that this works. First, a generational garbage collector may have created copies of the object during its lifetime, which are still floating around in unused memory. Second, an optimizing JVM may detect that you are not using the object afterwards and hence, eliminate all obsolete write operations. – Holger Dec 14 '18 at 14:49
  • Thank you @Holger ! this is crucial! – ElectRocnic Dec 14 '18 at 17:47
  • 2
    @ElectRocnic I suppose that you could use `Unsafe.allocateMemory()` and `Unsafe.freeMemory()` but JVM is slowly obsoleting `Unsafe` starting from Java 9 as far as I understand. – Karol Dowbecki Dec 14 '18 at 18:00
  • Thank you for your input, I will have a look at those! – ElectRocnic Dec 14 '18 at 19:20