1

I am looking for a way to store a secret on a Windows computer so that even the administrator cannot access it.

But executables that are signed with a specific code signing certificate should be able to access that secret without user interaction.


I was thinking about using the following approach:

  • Create a new Windows user "SecretKeeper" with a random password that is not known to any user.
  • Install a Windows Service running under the SecretKeeper user account. (The Service can be started automatically by Windows without anyone else knowing the password of SecretKeeper)
  • Give the secret to that Service, have it store the file on the file system and encrypt it using the Windows File Encryption API (so only that specific user SecretKeeper can read the file)
  • When an application needs the secret, it can communicate with the service in a way so that the service can check the code signature of the executable before sending the secret.

Problem with this approach is that an administrator can exchange the service executable with their own executable that is then started running as SecretKeeper and can decrypt the file.


Is there some way to make sure the executable for an installed Windows service is not exchanged even by the administrator or is there maybe a completely different approach to achieve the goal of hiding a secret even from the administrator?


Note: I am aware that a local administrator of a Windows computer has other means to access process memory of running processes or watch communication between processes and that there would have to be other mechanisms to prevent that.


This question is similar to the following questions:

NineBerry
  • 121
  • 8
  • 7
    The administrator has complete access to the system, including the ability to load kernel drivers, and likely also has physical access to the hardware. You can't stop them from gaining access to something. If you could, DRM would be a solved problem. Even Intel Management Engine, whose firmware was intended to be secret and heavily protected, was compromised eventually by a handful of researchers. – Polynomial Feb 15 '18 at 10:48
  • 8
    This approach wouldn't even work. In order for Windows to decrypt the secret, the service needs to be logged in as an *Authenticated* user (meaning a password was supplied); that password would be stored in the service configuration database. The administrator could just read the password out of the service list. If that *wasn't* the case, the Administrator could instead just launch a process as the SecretKeeper user with an unauthenticated token (Administrator, like SYSTEM, can create arbitrary tokens) and decrypt the secret that way. ***What you ask cannot be done.*** – CBHacking Feb 15 '18 at 10:54
  • Use a small truecrypt container file and give it a random system files-like name (i.e. msvcrt10.dll). The put it in Windows/system32. – Overmind Feb 15 '18 at 11:36
  • That's like building a box that will be send to the customer's house, and asking how to prevent the customer from opening that box. – Johannes Kuhn Feb 15 '18 at 12:24
  • just use a password-protected archive. – dandavis Feb 15 '18 at 12:40
  • @CBHacking How can a user read a password from the service configuration database? Is this officially supported by Microsoft or do you need some specific tools for that? – NineBerry Feb 15 '18 at 16:29
  • @NineBerry Reading passwords out of the registry - even ones stored under reversible encryption, the way that service passwords must be - is *not exactly* supported, but it is documented. https://blogs.technet.microsoft.com/heyscriptingguy/2012/07/06/use-powershell-to-decrypt-lsa-secrets-from-the-registry/ walks you though it, for example; you can also find simple downloads that do it for you. The secrets are stored in the SECURITY registry hive, and are encrypted, but Administrators can access and decrypt them. – CBHacking Feb 15 '18 at 20:42
  • You only can do that with hardware support. This is what TPMs are used for. However this has some limitations to when the secret can be used (as opposed to exported). You could enforce them only with secure boot. – eckes Apr 19 '18 at 02:24

2 Answers2

2

To be honest, that's probably not even the weakest point in your scheme. If I was the admin trying to get the secret, all I'd do is decompile the app that's requesting the secret (to see how it does it), and just build a quick .exe that politely asks your service for the secret. I mean, your secret-keeper doesn't really have any way of knowing whether the app requesting the secret is authorized to have it.

I think the short answer is: you really can't do what you're asking.

Kevin
  • 852
  • 5
  • 10
  • I have written in the question: "When an application needs the secret, it can communicate with the service in a way so that the service can check the code signature of the executable before sending the secret." So, an attacker cannot simply write an own executable if they don't have the private key of the code signing certificate we check the executable against. – NineBerry Feb 15 '18 at 15:48
  • If you're reverse engineering things, it would be far, far better to do it to the SecretKeeper itself. You're admin; you can read, write, and debug any executable or process on the system. You could also do things like set up the SecretKeeper binary (using the registry, no need to tamper with the executable) such that when it launches it gets launched under a debugger that steals the secret, or gets an injected DLL that launches a child process to pull the secret off the file system, or... I *do* agree with your last line. This is not going to happen. – CBHacking Feb 15 '18 at 20:51
  • @CBHacking Putting something like the FIPS-mode self-tests on the SecretKeeper application would slow down reverse-engineering attempts. – Mike Ounsworth Aug 14 '18 at 21:15
  • It can't be done. You cannot protect anything from the admin. Admin can debug the SecretKeeping service, put a breakpoint on the instruction checking the signature, and change the code from `execute if signature ok` to `execute if signature fails`. And done. Even asking user to supply a password cannot protect it, as admin can install a kernel-level keylogger, and you cannot detect that. Admin can dump memory, can change libraries, can do anything he wants. – ThoriumBR Aug 30 '18 at 12:16
1

Seed Passwords

The approach I'd use (given appropriate knowhow) would be to encrypt your data using a seed value that you personally know and never write down.

Essentially, you'd need to know the word, phrase or random string of values/characters that were originally used to encode the data in order to decode it, so your secret-keeping application is utterly useless without that data, even if the Administrator has full code access to it and can decompile and recompile at will.

This is substantially different from a password protected system in that the encoding isn't common across protected files and the password doesn't have to be stored anywhere except your own head. This isn't a permission system, this is literally an integral part of the process of decoding your data.

The only way it could be bypassed would be to either brute force decode the raw data (good luck with that!) or key-log the input of the seed value when it's in use.

For damn-near perfect security, keep your encoding application on a secured external device so that the tool isn't readily accessible to the administrator, only the produced encrypted files.
You'd plug it in, the external device would accept your input file and encode/decode it using an encryption seed you type into a keypad (which doesn't communicate with the compromised computer) before it spits out the encrypted or decrypted file onto the hosting machine.

This approach is pretty much only vulnerable to social-engineering/physical attacks where the attacker physically gains control over the encryption device and compels you to tell them the password.

Ruadhan2300
  • 561
  • 3
  • 3
  • Vialotes this requirement in the question: "But executables that are signed with a specific code signing certificate should be able to access that secret without user interaction." – NineBerry Aug 30 '18 at 13:48
  • Whoops. I forgot about that one, got caught up in my fancy solution. – Ruadhan2300 Aug 30 '18 at 13:52