Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crypt32Util.cryptProtectData leaves security sensitive information in memory #1362

Closed
dmytro-sheyko opened this issue Aug 8, 2021 · 0 comments · Fixed by #1366
Closed

Crypt32Util.cryptProtectData leaves security sensitive information in memory #1362

dmytro-sheyko opened this issue Aug 8, 2021 · 0 comments · Fixed by #1366

Comments

@dmytro-sheyko
Copy link

JNA version: 5.8.0
jna-platform.jar (+ jna.jar)

Java Version: 1.8.0_261
java -version
java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)

OS Version: Windows 10
Microsoft Windows [Version 10.0.18363.1556]


Description of the problem
The method Crypt32Util.cryptProtectData (and Crypt32Util.cryptUnprotectData) do not clean copy of security sensitive information and leave it in memory. This can be considered as security vulnerability since it becomes possible to reveal passwords from memory dumps.


Code that reproduces the bug

import com.sun.jna.Memory;
import com.sun.jna.platform.win32.Crypt32Util;
import com.sun.jna.platform.win32.WinCrypt;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.Arrays;

public class JNACryptProtectDataSecurityIssue {
	public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
		Field fldMemory_HEAD = Memory.class.getDeclaredField("HEAD");
		fldMemory_HEAD.setAccessible(true);
		Field fldLinkedReference_next = Class.forName("com.sun.jna.Memory$LinkedReference").getDeclaredField("next");
		fldLinkedReference_next.setAccessible(true);
		Field fldLinkedReference_prev = Class.forName("com.sun.jna.Memory$LinkedReference").getDeclaredField("prev");
		fldLinkedReference_prev.setAccessible(true);
		System.out.println("-----");
		byte[] data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, };
		byte[] encrypted = Crypt32Util.cryptProtectData(data, WinCrypt.CRYPTPROTECT_UI_FORBIDDEN);
		byte[] decrypted = Crypt32Util.cryptUnprotectData(encrypted, WinCrypt.CRYPTPROTECT_UI_FORBIDDEN);
		System.out.println("-----");
		{
			Object head = fldMemory_HEAD.get(null);
			Object next = head;
			do {
				Object curr = next;
				Memory memory = (Memory) ((WeakReference<?>) curr).get();
				byte[] array = memory.getByteArray(0, (int) memory.size());
				if (Arrays.equals(array, encrypted)) {
					System.out.println("!!! encrypted data found !!!");
				}
				if (Arrays.equals(array, data)) {
					System.out.println("!!! decrypted data found !!!");
				}
				next = fldLinkedReference_next.get(curr);
			} while (next != null);
		}
		System.out.println("-----");
	}
}

Expected

-----
-----
-----

Actual

-----
-----
!!! encrypted data found !!!
!!! decrypted data found !!!
-----
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant