LSA private data
editThe Local Security Authority (LSA) of Windows can store private data: secrets encrypted on disk, which only their creator and the administrators can read. Services use it to keep a secret for the whole machine. LsaPrivateData from the Meziantou.Framework.Win32.Lsa package reads and writes it.
dotnet package add Meziantou.Framework.Win32.LsaBefore using it, consider the data protection API (DPAPI), exposed by System.Security.Cryptography.ProtectedData: Microsoft recommends it over the LSA private data, unless you specifically need to manipulate LSA secrets. To store the credentials of a user, see Credential Manager.
The examples of this page change the secrets of the machine and require administrator rights: they are compiled, not run, by the build of the repository.
Store, read and remove a secret
Store a value under a key:
// Requires administrator privileges
LsaPrivateData.SetValue("L$MySecretKey", "MySecretValue");Read it back. GetValue returns null when the key does not exist:
var value = LsaPrivateData.GetValue("L$MySecretKey");
if (value is not null)
{
Console.WriteLine($"Retrieved value: {value}");
}
else
{
Console.WriteLine("Key not found");
}Remove it. Removing a key that does not exist does nothing, and SetValue with a null value removes the key too:
// Requires administrator privileges
LsaPrivateData.RemoveValue("L$MySecretKey");- SetValue and RemoveValue require administrator rights. GetValue requires the rights that the secret grants: its creator and the administrators.
- The methods throw a
Win32Exceptionwhen Windows rejects the operation, for instance with error5(access denied) when the process is not elevated. - The key cannot be
nullor empty.
Choose the key
The prefix of the key decides the kind of secret, and who can reach it:
| Prefix | Kind | Reach |
|---|---|---|
L$ | Local | Cannot be read remotely |
G$ | Global | Can be read remotely |
M$ | Machine | Only the operating system can read it back |
| None | Global | Can be read remotely |
A key without a prefix can be read remotely. Use the L$ prefix, as in the examples, unless you need otherwise.
Security
- The value is encrypted on disk and protected by an access control list, but LSA secrets are a well-known target for anyone who already has administrator or SYSTEM access to the machine. They are not absolutely protected.
- GetValue returns a
string: it cannot be cleared from memory once you are done with it, and it stays readable in a memory dump until the garbage collector reuses its memory. The library clears the native copy of the secret.